1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "../../include/fxcrt/fx_basic.h"
8 #if _FXM_PLATFORM_ != _FXM_PLATFORM_WINDOWS_
9 #include <sys/types.h>
10 #include <dirent.h>
11 #else
12 #include <direct.h>
13 #endif
~CFX_PrivateData()14 CFX_PrivateData::~CFX_PrivateData()
15 {
16 ClearAll();
17 }
FreeData()18 void FX_PRIVATEDATA::FreeData()
19 {
20 if (m_pData == NULL) {
21 return;
22 }
23 if (m_bSelfDestruct) {
24 delete (CFX_DestructObject*)m_pData;
25 } else if (m_pCallback) {
26 m_pCallback(m_pData);
27 }
28 }
AddData(FX_LPVOID pModuleId,FX_LPVOID pData,PD_CALLBACK_FREEDATA callback,FX_BOOL bSelfDestruct)29 void CFX_PrivateData::AddData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback, FX_BOOL bSelfDestruct)
30 {
31 if (pModuleId == NULL) {
32 return;
33 }
34 FX_PRIVATEDATA* pList = m_DataList.GetData();
35 int count = m_DataList.GetSize();
36 for (int i = 0; i < count; i ++) {
37 if (pList[i].m_pModuleId == pModuleId) {
38 pList[i].FreeData();
39 pList[i].m_pData = pData;
40 pList[i].m_pCallback = callback;
41 return;
42 }
43 }
44 FX_PRIVATEDATA data = {pModuleId, pData, callback, bSelfDestruct};
45 m_DataList.Add(data);
46 }
SetPrivateData(FX_LPVOID pModuleId,FX_LPVOID pData,PD_CALLBACK_FREEDATA callback)47 void CFX_PrivateData::SetPrivateData(FX_LPVOID pModuleId, FX_LPVOID pData, PD_CALLBACK_FREEDATA callback)
48 {
49 AddData(pModuleId, pData, callback, FALSE);
50 }
SetPrivateObj(FX_LPVOID pModuleId,CFX_DestructObject * pObj)51 void CFX_PrivateData::SetPrivateObj(FX_LPVOID pModuleId, CFX_DestructObject* pObj)
52 {
53 AddData(pModuleId, pObj, NULL, TRUE);
54 }
RemovePrivateData(FX_LPVOID pModuleId)55 FX_BOOL CFX_PrivateData::RemovePrivateData(FX_LPVOID pModuleId)
56 {
57 if (pModuleId == NULL) {
58 return FALSE;
59 }
60 FX_PRIVATEDATA* pList = m_DataList.GetData();
61 int count = m_DataList.GetSize();
62 for (int i = 0; i < count; i ++) {
63 if (pList[i].m_pModuleId == pModuleId) {
64 m_DataList.RemoveAt(i);
65 return TRUE;
66 }
67 }
68 return FALSE;
69 }
GetPrivateData(FX_LPVOID pModuleId)70 FX_LPVOID CFX_PrivateData::GetPrivateData(FX_LPVOID pModuleId)
71 {
72 if (pModuleId == NULL) {
73 return NULL;
74 }
75 FX_PRIVATEDATA* pList = m_DataList.GetData();
76 int count = m_DataList.GetSize();
77 for (int i = 0; i < count; i ++) {
78 if (pList[i].m_pModuleId == pModuleId) {
79 return pList[i].m_pData;
80 }
81 }
82 return NULL;
83 }
ClearAll()84 void CFX_PrivateData::ClearAll()
85 {
86 FX_PRIVATEDATA* pList = m_DataList.GetData();
87 int count = m_DataList.GetSize();
88 for (int i = 0; i < count; i ++) {
89 pList[i].FreeData();
90 }
91 m_DataList.RemoveAll();
92 }
FX_atonum(FX_BSTR strc,FX_BOOL & bInteger,void * pData)93 void FX_atonum(FX_BSTR strc, FX_BOOL& bInteger, void* pData)
94 {
95 if (FXSYS_memchr(strc.GetPtr(), '.', strc.GetLength()) == NULL) {
96 bInteger = TRUE;
97 int cc = 0, integer = 0;
98 FX_LPCSTR str = strc.GetCStr();
99 int len = strc.GetLength();
100 FX_BOOL bNegative = FALSE;
101 if (str[0] == '+') {
102 cc++;
103 } else if (str[0] == '-') {
104 bNegative = TRUE;
105 cc++;
106 }
107 while (cc < len) {
108 if (str[cc] < '0' || str[cc] > '9') {
109 break;
110 }
111 integer = integer * 10 + str[cc] - '0';
112 if (integer < 0) {
113 break;
114 }
115 cc ++;
116 }
117 if (bNegative) {
118 integer = -integer;
119 }
120 *(int*)pData = integer;
121 } else {
122 bInteger = FALSE;
123 *(FX_FLOAT*)pData = FX_atof(strc);
124 }
125 }
FX_atof(FX_BSTR strc)126 FX_FLOAT FX_atof(FX_BSTR strc)
127 {
128 if (strc.GetLength() == 0) {
129 return 0.0;
130 }
131 int cc = 0;
132 FX_BOOL bNegative = FALSE;
133 FX_LPCSTR str = strc.GetCStr();
134 int len = strc.GetLength();
135 if (str[0] == '+') {
136 cc++;
137 } else if (str[0] == '-') {
138 bNegative = TRUE;
139 cc++;
140 }
141 while (cc < len) {
142 if (str[cc] != '+' && str[cc] != '-') {
143 break;
144 }
145 cc ++;
146 }
147 FX_FLOAT value = 0;
148 while (cc < len) {
149 if (str[cc] == '.') {
150 break;
151 }
152 value = value * 10 + str[cc] - '0';
153 cc ++;
154 }
155 static const FX_FLOAT fraction_scales[] = {0.1f, 0.01f, 0.001f, 0.0001f, 0.00001f, 0.000001f,
156 0.0000001f, 0.00000001f, 0.000000001f, 0.0000000001f, 0.00000000001f
157 };
158 int scale = 0;
159 if (cc < len && str[cc] == '.') {
160 cc ++;
161 while (cc < len) {
162 value += fraction_scales[scale] * (str[cc] - '0');
163 scale ++;
164 if (scale == sizeof fraction_scales / sizeof(FX_FLOAT)) {
165 break;
166 }
167 cc ++;
168 }
169 }
170 return bNegative ? -value : value;
171 }
172
173 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
FXSYS_snprintf(char * str,size_t size,_Printf_format_string_ const char * fmt,...)174 void FXSYS_snprintf(char *str, size_t size, _Printf_format_string_ const char* fmt, ...)
175 {
176 va_list ap;
177 va_start(ap, fmt);
178 FXSYS_vsnprintf(str, size, fmt, ap);
179 va_end(ap);
180 }
FXSYS_vsnprintf(char * str,size_t size,const char * fmt,va_list ap)181 void FXSYS_vsnprintf(char *str, size_t size, const char* fmt, va_list ap)
182 {
183 (void) _vsnprintf(str, size, fmt, ap);
184 if (size) {
185 str[size - 1] = 0;
186 }
187 }
188 #endif // _FXM_PLATFORM_WINDOWS_ && _MSC_VER < 1900
189
FX_IsDigit(FX_BYTE ch)190 static FX_BOOL FX_IsDigit(FX_BYTE ch)
191 {
192 return (ch >= '0' && ch <= '9') ? TRUE : FALSE;
193 }
FX_IsXDigit(FX_BYTE ch)194 static FX_BOOL FX_IsXDigit(FX_BYTE ch)
195 {
196 return (FX_IsDigit(ch) || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) ? TRUE : FALSE;
197 }
FX_MakeUpper(FX_BYTE ch)198 static FX_BYTE FX_MakeUpper(FX_BYTE ch)
199 {
200 if (ch < 'a' || ch > 'z') {
201 return ch;
202 }
203 return ch - 32;
204 }
FX_HexToI(FX_BYTE ch)205 static int FX_HexToI(FX_BYTE ch)
206 {
207 ch = FX_MakeUpper(ch);
208 return FX_IsDigit(ch) ? (ch - '0') : (ch - 55);
209 }
210 static const unsigned char url_encodeTable[128] = {
211 1, 1, 1, 1, 1, 1, 1, 1,
212 1, 1, 1, 1, 1, 1, 1, 1,
213 1, 1, 1, 1, 1, 1, 1, 1,
214 1, 1, 1, 1, 1, 1, 1, 1,
215 1, 0, 1, 1, 0, 1, 0, 0,
216 0, 0, 0, 0, 0, 0, 0, 0,
217 0, 0, 0, 0, 0, 0, 0, 0,
218 0, 0, 0, 0, 1, 0, 1, 0,
219 0, 0, 0, 0, 0, 0, 0, 0,
220 0, 0, 0, 0, 0, 0, 0, 0,
221 0, 0, 0, 0, 0, 0, 0, 0,
222 0, 0, 0, 1, 1, 1, 1, 0,
223 1, 0, 0, 0, 0, 0, 0, 0,
224 0, 0, 0, 0, 0, 0, 0, 0,
225 0, 0, 0, 0, 0, 0, 0, 0,
226 0, 0, 0, 1, 1, 1, 1, 1,
227 };
FX_UrlEncode(const CFX_WideString & wsUrl)228 CFX_ByteString FX_UrlEncode(const CFX_WideString& wsUrl)
229 {
230 const char arDigits[] = "0123456789ABCDEF";
231 CFX_ByteString rUrl;
232 int nLength = wsUrl.GetLength();
233 for (int i = 0; i < nLength; i++) {
234 FX_DWORD word = wsUrl.GetAt(i);
235 if (word > 0x7F || url_encodeTable[word] == 1) {
236 CFX_ByteString bsUri = CFX_ByteString::FromUnicode((FX_WORD)word);
237 int nByte = bsUri.GetLength();
238 for (int j = 0; j < nByte; j++) {
239 rUrl += '%';
240 FX_BYTE code = bsUri.GetAt(j);
241 rUrl += arDigits[code >> 4];
242 rUrl += arDigits[code & 0x0F];
243 }
244 } else {
245 rUrl += CFX_ByteString::FromUnicode((FX_WORD)word);
246 }
247 }
248 return rUrl;
249 }
FX_UrlDecode(const CFX_ByteString & bsUrl)250 CFX_WideString FX_UrlDecode(const CFX_ByteString& bsUrl)
251 {
252 CFX_ByteString rUrl;
253 int nLength = bsUrl.GetLength();
254 for (int i = 0; i < nLength; i++) {
255 if (i < nLength - 2 && bsUrl[i] == '%' && FX_IsXDigit(bsUrl[i + 1]) && FX_IsXDigit(bsUrl[i + 2])) {
256 rUrl += (FX_HexToI(bsUrl[i + 1]) << 4 | FX_HexToI(bsUrl[i + 2]));
257 i += 2;
258 } else {
259 rUrl += bsUrl[i];
260 }
261 }
262 return CFX_WideString::FromLocal(rUrl);
263 }
FX_EncodeURI(const CFX_WideString & wsURI)264 CFX_ByteString FX_EncodeURI(const CFX_WideString& wsURI)
265 {
266 const char arDigits[] = "0123456789ABCDEF";
267 CFX_ByteString rURI;
268 CFX_ByteString bsUri = wsURI.UTF8Encode();
269 int nLength = bsUri.GetLength();
270 for (int i = 0; i < nLength; i++) {
271 FX_BYTE code = bsUri.GetAt(i);
272 if (code > 0x7F || url_encodeTable[code] == 1) {
273 rURI += '%';
274 rURI += arDigits[code >> 4];
275 rURI += arDigits[code & 0x0F];
276 } else {
277 rURI += code;
278 }
279 }
280 return rURI;
281 }
FX_DecodeURI(const CFX_ByteString & bsURI)282 CFX_WideString FX_DecodeURI(const CFX_ByteString& bsURI)
283 {
284 CFX_ByteString rURI;
285 int nLength = bsURI.GetLength();
286 for (int i = 0; i < nLength; i++) {
287 if (i < nLength - 2 && bsURI[i] == '%' && FX_IsXDigit(bsURI[i + 1]) && FX_IsXDigit(bsURI[i + 2])) {
288 rURI += (FX_HexToI(bsURI[i + 1]) << 4 | FX_HexToI(bsURI[i + 2]));
289 i += 2;
290 } else {
291 rURI += bsURI[i];
292 }
293 }
294 return CFX_WideString::FromUTF8(rURI, rURI.GetLength());
295 }
296 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
297 class CFindFileData
298 {
299 public:
~CFindFileData()300 virtual ~CFindFileData() {}
301 HANDLE m_Handle;
302 FX_BOOL m_bEnd;
303 };
304 class CFindFileDataA : public CFindFileData
305 {
306 public:
~CFindFileDataA()307 virtual ~CFindFileDataA() {}
308 WIN32_FIND_DATAA m_FindData;
309 };
310 class CFindFileDataW : public CFindFileData
311 {
312 public:
~CFindFileDataW()313 virtual ~CFindFileDataW() {}
314 WIN32_FIND_DATAW m_FindData;
315 };
316 #endif
FX_OpenFolder(FX_LPCSTR path)317 void* FX_OpenFolder(FX_LPCSTR path)
318 {
319 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
320 #ifndef _WIN32_WCE
321 CFindFileDataA* pData = new CFindFileDataA;
322 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
323 pData->m_Handle = FindFirstFileA(CFX_ByteString(path) + "/*.*", &pData->m_FindData);
324 #else
325 pData->m_Handle = FindFirstFileExA(CFX_ByteString(path) + "/*.*", FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
326 #endif
327 #else
328 CFindFileDataW* pData = new CFindFileDataW;
329 pData->m_Handle = FindFirstFileW(CFX_WideString::FromLocal(path) + L"/*.*", &pData->m_FindData);
330 #endif
331 if (pData->m_Handle == INVALID_HANDLE_VALUE) {
332 delete pData;
333 return NULL;
334 }
335 pData->m_bEnd = FALSE;
336 return pData;
337 #else
338 DIR* dir = opendir(path);
339 return dir;
340 #endif
341 }
FX_OpenFolder(FX_LPCWSTR path)342 void* FX_OpenFolder(FX_LPCWSTR path)
343 {
344 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
345 CFindFileDataW* pData = new CFindFileDataW;
346 #ifdef _FX_WINAPI_PARTITION_DESKTOP_
347 pData->m_Handle = FindFirstFileW((CFX_WideString(path) + L"/*.*").c_str(), &pData->m_FindData);
348 #else
349 pData->m_Handle = FindFirstFileExW((CFX_WideString(path) + L"/*.*").c_str(), FindExInfoStandard, &pData->m_FindData, FindExSearchNameMatch, NULL, 0);
350 #endif
351 if (pData->m_Handle == INVALID_HANDLE_VALUE) {
352 delete pData;
353 return NULL;
354 }
355 pData->m_bEnd = FALSE;
356 return pData;
357 #else
358 DIR* dir = opendir(CFX_ByteString::FromUnicode(path));
359 return dir;
360 #endif
361 }
FX_GetNextFile(void * handle,CFX_ByteString & filename,FX_BOOL & bFolder)362 FX_BOOL FX_GetNextFile(void* handle, CFX_ByteString& filename, FX_BOOL& bFolder)
363 {
364 if (handle == NULL) {
365 return FALSE;
366 }
367 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
368 #ifndef _WIN32_WCE
369 CFindFileDataA* pData = (CFindFileDataA*)handle;
370 if (pData->m_bEnd) {
371 return FALSE;
372 }
373 filename = pData->m_FindData.cFileName;
374 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
375 if (!FindNextFileA(pData->m_Handle, &pData->m_FindData)) {
376 pData->m_bEnd = TRUE;
377 }
378 return TRUE;
379 #else
380 CFindFileDataW* pData = (CFindFileDataW*)handle;
381 if (pData->m_bEnd) {
382 return FALSE;
383 }
384 filename = CFX_ByteString::FromUnicode(pData->m_FindData.cFileName);
385 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
386 if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
387 pData->m_bEnd = TRUE;
388 }
389 return TRUE;
390 #endif
391 #elif defined(__native_client__)
392 abort();
393 return FALSE;
394 #else
395 struct dirent *de = readdir((DIR*)handle);
396 if (de == NULL) {
397 return FALSE;
398 }
399 filename = de->d_name;
400 bFolder = de->d_type == DT_DIR;
401 return TRUE;
402 #endif
403 }
FX_GetNextFile(void * handle,CFX_WideString & filename,FX_BOOL & bFolder)404 FX_BOOL FX_GetNextFile(void* handle, CFX_WideString& filename, FX_BOOL& bFolder)
405 {
406 if (handle == NULL) {
407 return FALSE;
408 }
409 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
410 CFindFileDataW* pData = (CFindFileDataW*)handle;
411 if (pData->m_bEnd) {
412 return FALSE;
413 }
414 filename = pData->m_FindData.cFileName;
415 bFolder = pData->m_FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
416 if (!FindNextFileW(pData->m_Handle, &pData->m_FindData)) {
417 pData->m_bEnd = TRUE;
418 }
419 return TRUE;
420 #elif defined(__native_client__)
421 abort();
422 return FALSE;
423 #else
424 struct dirent *de = readdir((DIR*)handle);
425 if (de == NULL) {
426 return FALSE;
427 }
428 filename = CFX_WideString::FromLocal(de->d_name);
429 bFolder = de->d_type == DT_DIR;
430 return TRUE;
431 #endif
432 }
FX_CloseFolder(void * handle)433 void FX_CloseFolder(void* handle)
434 {
435 if (handle == NULL) {
436 return;
437 }
438 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
439 CFindFileData* pData = (CFindFileData*)handle;
440 FindClose(pData->m_Handle);
441 delete pData;
442 #else
443 closedir((DIR*)handle);
444 #endif
445 }
FX_GetFolderSeparator()446 FX_WCHAR FX_GetFolderSeparator()
447 {
448 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
449 return '\\';
450 #else
451 return '/';
452 #endif
453 }
454
Inverse()455 CFX_Matrix_3by3 CFX_Matrix_3by3::Inverse()
456 {
457 FX_FLOAT det = a*(e*i - f*h) - b*(i*d - f*g) + c*(d*h - e*g);
458 if (FXSYS_fabs(det) < 0.0000001)
459 return CFX_Matrix_3by3();
460 else
461 return CFX_Matrix_3by3(
462 (e*i - f*h) / det,
463 -(b*i - c*h) / det,
464 (b*f - c*e) / det,
465 -(d*i - f*g) / det,
466 (a*i - c*g) / det,
467 -(a*f - c*d) / det,
468 (d*h - e*g) / det,
469 -(a*h - b*g) / det,
470 (a*e - b*d) / det
471 );
472 }
473
Multiply(const CFX_Matrix_3by3 & m)474 CFX_Matrix_3by3 CFX_Matrix_3by3::Multiply(const CFX_Matrix_3by3 &m)
475 {
476 return CFX_Matrix_3by3(
477 a*m.a + b*m.d + c*m.g,
478 a*m.b + b*m.e + c*m.h,
479 a*m.c + b*m.f + c*m.i,
480 d*m.a + e*m.d + f*m.g,
481 d*m.b + e*m.e + f*m.h,
482 d*m.c + e*m.f + f*m.i,
483 g*m.a + h*m.d + i*m.g,
484 g*m.b + h*m.e + i*m.h,
485 g*m.c + h*m.f + i*m.i
486 );
487 }
488
TransformVector(const CFX_Vector_3by1 & v)489 CFX_Vector_3by1 CFX_Matrix_3by3::TransformVector(const CFX_Vector_3by1 &v)
490 {
491 return CFX_Vector_3by1(
492 a * v.a + b * v.b + c * v.c,
493 d * v.a + e * v.b + f * v.c,
494 g * v.a + h * v.b + i * v.c
495 );
496 }
497