| // Copyright 2014 PDFium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #include "../../include/fxcrt/fx_basic.h" | |
| #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_ | |
| #include <sys/types.h> | |
| #include <dirent.h> | |
| #else | |
| #include <direct.h> | |
| #endif | |
| CFX_PrivateData::~CFX_PrivateData() | |
| { | |
| ClearAll(); | |
| } | |
| void FX_PRIVATEDATA::FreeData() | |
| { | |
| if (m_pData == NULL) { | |
| return; | |
| } | |
| if (m_bSelfDestruct) { | |
| delete (CFX_DestructObject*)m_pData; | |
| } else if (m_pCallback) { | |
| m_pCallback(m_pData); | |
| } | |
| } | |
| void CFX_PrivateData::AddData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct) | |
| { | |
| if (pModuleId == NULL) { | |
| return; | |
| } | |
| FX_PRIVATEDATA* pList = m_DataList.GetData(); | |
| int count = m_DataList.GetSize(); | |
| for (int i = 0; i < count; i ++) { | |
| if (pList[i].m_pModuleId == pModuleId) { | |
| pList[i].FreeData(); | |
| pList[i].m_pData = pData; | |
| pList[i].m_pCallback = callback; | |
| return; | |
| } | |
| } | |
| FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct}; | |
| m_DataList.Add(data); | |
| } | |
| void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback) | |
| { | |
| AddData(pModuleId, pData, callback, FALSE); | |
| } | |
| void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj) | |
| { | |
| AddData(pModuleId, pObj, NULL, TRUE); | |
| } | |
| FX_BOOL CFX_PrivateData::RemovePrivateData(FX_LPVOID pModuleId) | |
| { | |
| if (pModuleId == NULL) { | |
| return FALSE; | |
| } | |
| FX_PRIVATEDATA* pList = m_DataList.GetData(); | |
| int count = m_DataList.GetSize(); | |
| for (int i = 0; i < count; i ++) { | |
| if (pList[i].m_pModuleId == pModuleId) { | |
| m_DataList.RemoveAt(i); | |
| return TRUE; | |
| } | |
| } | |
| return FALSE; | |
| } | |
| FX_LPVOID CFX_PrivateData::GetPrivateData(FX_LPVOID pModuleId) | |
| { | |
| if (pModuleId == NULL) { | |
| return NULL; | |
| } | |
| FX_PRIVATEDATA* pList = m_DataList.GetData(); | |
| int count = m_DataList.GetSize(); | |
| for (int i = 0; i < count; i ++) { | |
| if (pList[i].m_pModuleId == pModuleId) { | |
| return pList[i].m_pData; | |
| } | |
| } | |
| return NULL; | |
| } | |
| void CFX_PrivateData::ClearAll() | |
| { | |
| FX_PRIVATEDATA* pList = m_DataList.GetData(); | |
| int count = m_DataList.GetSize(); | |
| for (int i = 0; i < count; i ++) { | |
| pList[i].FreeData(); | |
| } | |
| m_DataList.RemoveAll(); | |
| } | |
| void FX_atonum(FX_BSTR strc, FX_BOOL& bInteger, void* pData) | |
| { | |
| if (FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength()) == NULL) { | |
| bInteger = TRUE; | |
| int cc = 0, integer = 0; | |
| FX_LPCSTR str = strc.GetCStr(); | |
| int len = strc.GetLength(); | |
| FX_BOOL bNegative = FALSE; | |
| if (str[0] == '+') { | |
| cc++; | |
| } else if (str[0] == '-') { | |
| bNegative = TRUE; | |
| cc++; | |
| } | |
| while (cc < len) { | |
| if (str[cc] < '0' || str[cc] > '9') { | |
| break; | |
| } | |
| integer = integer * 10 + str[cc] - '0'; | |
| if (integer < 0) { | |
| break; | |
| } | |
| cc ++; | |
| } | |
| if (bNegative) { | |
| integer = -integer; | |
| } | |
| *(int*)pData = integer; | |
| } else { | |
| bInteger = FALSE; | |
| *(FX_FLOAT*)pData = FX_atof(strc); | |
| } | |
| } | |
| FX_FLOAT FX_atof(FX_BSTR strc) | |
| { | |
| if (strc.GetLength() == 0) { | |
| return 0.0; | |
| } | |
| int cc = 0; | |
| FX_BOOL bNegative = FALSE; | |
| FX_LPCSTR str = strc.GetCStr(); | |
| int len = strc.GetLength(); | |
| if (str[0] == '+') { | |
| cc++; | |
| } else if (str[0] == '-') { | |
| bNegative = TRUE; | |
| cc++; | |
| } | |
| while (cc < len) { | |
| if (str[cc] != '+' && str[cc] != '-') { | |
| break; | |
| } | |
| cc ++; | |
| } | |
| FX_FLOAT value = 0; | |
| while (cc < len) { | |
| if (str[cc] == '.') { | |
| break; | |
| } | |
| value = value * 10 + str[cc] - '0'; | |
| cc ++; | |
| } | |
| static const FX_FLOAT fraction_scales[] = {0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f, | |
| 0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f | |
| }; | |
| int scale = 0; | |
| if (cc < len && str[cc] == '.') { | |
| cc ++; | |
| while (cc < len) { | |
| value += fraction_scales[scale] * (str[cc] - '0'); | |
| scale ++; | |
| if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) { | |
| break; | |
| } | |
| cc ++; | |
| } | |
| } | |
| return bNegative ? -value : value; | |
| } | |
| static FX_BOOL FX_IsDigit(FX_BYTE ch) | |
| { | |
| return (ch >= '0' && ch <= '9') ? TRUE : FALSE; | |
| } | |
| static FX_BOOL FX_IsXDigit(FX_BYTE ch) | |
| { | |
| return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE; | |
| } | |
| static FX_BYTE FX_MakeUpper(FX_BYTE ch) | |
| { | |
| if (ch < 'a' || ch > 'z') { | |
| return ch; | |
| } | |
| return ch - 32; | |
| } | |
| static int FX_HexToI(FX_BYTE ch) | |
| { | |
| ch = FX_MakeUpper(ch); | |
| return FX_IsDigit(ch) ? (ch - '0') : (ch - 55); | |
| } | |
| static const unsigned char url_encodeTable[128] = { | |
| 1, 1, 1, 1, 1, 1, 1, 1, | |
| 1, 1, 1, 1, 1, 1, 1, 1, | |
| 1, 1, 1, 1, 1, 1, 1, 1, | |
| 1, 1, 1, 1, 1, 1, 1, 1, | |
| 1, 0, 1, 1, 0, 1, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 1, 0, 1, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 1, 1, 1, 1, 0, | |
| 1, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 0, 0, 0, 0, 0, | |
| 0, 0, 0, 1, 1, 1, 1, 1, | |
| }; | |
| CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl) | |
| { | |
| const char arDigits[] = "0123456789ABCDEF"; | |
| CFX_ByteString rUrl; | |
| int nLength = wsUrl.GetLength(); | |
| for (int i = 0; i < nLength; i++) { | |
| FX_DWORD word = wsUrl.GetAt(i); | |
| if (word > 0x7F || url_encodeTable[word] == 1) { | |
| CFX_ByteString bsUri = CFX_ByteString::FromUnicode((FX_WORD)word); | |
| int nByte = bsUri.GetLength(); | |
| for (int j = 0; j < nByte; j++) { | |
| rUrl += '%'; | |
| FX_BYTE code = bsUri.GetAt(j); | |
| rUrl += arDigits[code >> 4]; | |
| rUrl += arDigits[code & 0x0F]; | |
| } | |
| } else { | |
| rUrl += CFX_ByteString::FromUnicode((FX_WORD)word); | |
| } | |
| } | |
| return rUrl; | |
| } | |
| CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl) | |
| { | |
| CFX_ByteString rUrl; | |
| int nLength = bsUrl.GetLength(); | |
| for (int i = 0; i < nLength; i++) { | |
| if (i < nLength - 2 && bsUrl[i] == '%' && FX_IsXDigit(bsUrl[i + 1]) && FX_IsXDigit(bsUrl[i + 2])) { | |
| rUrl += (FX_HexToI(bsUrl[i + 1]) << 4 | FX_HexToI(bsUrl[i + 2])); | |
| i += 2; | |
| } else { | |
| rUrl += bsUrl[i]; | |
| } | |
| } | |
| return CFX_WideString::FromLocal(rUrl); | |
| } | |
| CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI) | |
| { | |
| const char arDigits[] = "0123456789ABCDEF"; | |
| CFX_ByteString rURI; | |
| CFX_ByteString bsUri = wsURI.UTF8Encode(); | |
| int nLength = bsUri.GetLength(); | |
| for (int i = 0; i < nLength; i++) { | |
| FX_BYTE code = bsUri.GetAt(i); | |
| if (code > 0x7F || url_encodeTable[code] == 1) { | |
| rURI += '%'; | |
| rURI += arDigits[code >> 4]; | |
| rURI += arDigits[code & 0x0F]; | |
| } else { | |
| rURI += code; | |
| } | |
| } | |
| return rURI; | |
| } | |
| CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI) | |
| { | |
| CFX_ByteString rURI; | |
| int nLength = bsURI.GetLength(); | |
| for (int i = 0; i < nLength; i++) { | |
| if (i < nLength - 2 && bsURI[i] == '%' && FX_IsXDigit(bsURI[i + 1]) && FX_IsXDigit(bsURI[i + 2])) { | |
| rURI += (FX_HexToI(bsURI[i + 1]) << 4 | FX_HexToI(bsURI[i + 2])); | |
| i += 2; | |
| } else { | |
| rURI += bsURI[i]; | |
| } | |
| } | |
| return CFX_WideString::FromUTF8(rURI, rURI.GetLength()); | |
| } | |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| class CFindFileData : public CFX_Object | |
| { | |
| public: | |
| virtual ~CFindFileData() {} | |
| HANDLE m_Handle; | |
| FX_BOOL m_bEnd; | |
| }; | |
| class CFindFileDataA : public CFindFileData | |
| { | |
| public: | |
| virtual ~CFindFileDataA() {} | |
| WIN32_FIND_DATAA m_FindData; | |
| }; | |
| class CFindFileDataW : public CFindFileData | |
| { | |
| public: | |
| virtual ~CFindFileDataW() {} | |
| WIN32_FIND_DATAW m_FindData; | |
| }; | |
| #endif | |
| void* FX_OpenFolder(FX_LPCSTR path) | |
| { | |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| #ifndef _WIN32_WCE | |
| CFindFileDataA* pData = FX_NEW CFindFileDataA; | |
| if (!pData) { | |
| return NULL; | |
| } | |
| #ifdef _FX_WINAPI_PARTITION_DESKTOP_ | |
| pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData); | |
| #else | |
| pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0); | |
| #endif | |
| #else | |
| CFindFileDataW* pData = FX_NEW CFindFileDataW; | |
| if (!pData) { | |
| return NULL; | |
| } | |
| pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData); | |
| #endif | |
| if (pData->m_Handle == INVALID_HANDLE_VALUE) { | |
| delete pData; | |
| return NULL; | |
| } | |
| pData->m_bEnd = FALSE; | |
| return pData; | |
| #else | |
| DIR* dir = opendir(path); | |
| return dir; | |
| #endif | |
| } | |
| void* FX_OpenFolder(FX_LPCWSTR path) | |
| { | |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| CFindFileDataW* pData = FX_NEW CFindFileDataW; | |
| if (!pData) { | |
| return NULL; | |
| } | |
| #ifdef _FX_WINAPI_PARTITION_DESKTOP_ | |
| pData->m_Handle = FindFirstFileW(CFX_WideString(path) + L"/*.*", &pData->m_FindData); | |
| #else | |
| pData->m_Handle = FindFirstFileExW(CFX_WideString(path) + L"/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0); | |
| #endif | |
| if (pData->m_Handle == INVALID_HANDLE_VALUE) { | |
| delete pData; | |
| return NULL; | |
| } | |
| pData->m_bEnd = FALSE; | |
| return pData; | |
| #else | |
| DIR* dir = opendir(CFX_ByteString::FromUnicode(path)); | |
| return dir; | |
| #endif | |
| } | |
| FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder) | |
| { | |
| if (handle == NULL) { | |
| return FALSE; | |
| } | |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| #ifndef _WIN32_WCE | |
| CFindFileDataA* pData = (CFindFileDataA*)handle; | |
| if (pData->m_bEnd) { | |
| return FALSE; | |
| } | |
| filename = pData->m_FindData.cFileName; | |
| bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; | |
| if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) { | |
| pData->m_bEnd = TRUE; | |
| } | |
| return TRUE; | |
| #else | |
| CFindFileDataW* pData = (CFindFileDataW*)handle; | |
| if (pData->m_bEnd) { | |
| return FALSE; | |
| } | |
| filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName); | |
| bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; | |
| if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) { | |
| pData->m_bEnd = TRUE; | |
| } | |
| return TRUE; | |
| #endif | |
| #elif defined(__native_client__) | |
| abort(); | |
| return FALSE; | |
| #else | |
| struct dirent *de = readdir((DIR*)handle); | |
| if (de == NULL) { | |
| return FALSE; | |
| } | |
| filename = de->d_name; | |
| bFolder = de->d_type == DT_DIR; | |
| return TRUE; | |
| #endif | |
| } | |
| FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder) | |
| { | |
| if (handle == NULL) { | |
| return FALSE; | |
| } | |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| CFindFileDataW* pData = (CFindFileDataW*)handle; | |
| if (pData->m_bEnd) { | |
| return FALSE; | |
| } | |
| filename = pData->m_FindData.cFileName; | |
| bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY; | |
| if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) { | |
| pData->m_bEnd = TRUE; | |
| } | |
| return TRUE; | |
| #elif defined(__native_client__) | |
| abort(); | |
| return FALSE; | |
| #else | |
| struct dirent *de = readdir((DIR*)handle); | |
| if (de == NULL) { | |
| return FALSE; | |
| } | |
| filename = CFX_WideString::FromLocal(de->d_name); | |
| bFolder = de->d_type == DT_DIR; | |
| return TRUE; | |
| #endif | |
| } | |
| void FX_CloseFolder(void* handle) | |
| { | |
| if (handle == NULL) { | |
| return; | |
| } | |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| CFindFileData* pData = (CFindFileData*)handle; | |
| FindClose(pData->m_Handle); | |
| delete pData; | |
| #else | |
| closedir((DIR*)handle); | |
| #endif | |
| } | |
| FX_WCHAR FX_GetFolderSeparator() | |
| { | |
| #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | |
| return '\\'; | |
| #else | |
| return '/'; | |
| #endif | |
| } | |
| CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse() | |
| { | |
| FX_FLOAT det = a*(e*i - f*h) - b*(i*d - f*g) + c*(d*h - e*g); | |
| if (FXSYS_fabs(det) < 0.0000001) | |
| return CFX_Matrix_3by3(); | |
| else | |
| return CFX_Matrix_3by3( | |
| (e*i - f*h) / det, | |
| -(b*i - c*h) / det, | |
| (b*f - c*e) / det, | |
| -(d*i - f*g) / det, | |
| (a*i - c*g) / det, | |
| -(a*f - c*d) / det, | |
| (d*h - e*g) / det, | |
| -(a*h - b*g) / det, | |
| (a*e - b*d) / det | |
| ); | |
| } | |
| CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3 &m) | |
| { | |
| return CFX_Matrix_3by3( | |
| a*m.a + b*m.d + c*m.g, | |
| a*m.b + b*m.e + c*m.h, | |
| a*m.c + b*m.f + c*m.i, | |
| d*m.a + e*m.d + f*m.g, | |
| d*m.b + e*m.e + f*m.h, | |
| d*m.c + e*m.f + f*m.i, | |
| g*m.a + h*m.d + i*m.g, | |
| g*m.b + h*m.e + i*m.h, | |
| g*m.c + h*m.f + i*m.i | |
| ); | |
| } | |
| CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1 &v) | |
| { | |
| return CFX_Vector_3by1( | |
| a * v.a + b * v.b + c * v.c, | |
| d * v.a + e * v.b + f * v.c, | |
| g * v.a + h * v.b + i * v.c | |
| ); | |
| } |