1 // Copyright 2019 Google LLC. 2 // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3 4 #include "SkLoadICU.h" 5 6 #if defined(_WIN32) && defined(SK_USING_THIRD_PARTY_ICU) 7 8 #ifndef WIN32_LEAN_AND_MEAN 9 #define WIN32_LEAN_AND_MEAN 10 #endif 11 #include <windows.h> 12 #include <io.h> 13 14 #include <cstdio> 15 #include <cstring> 16 #include <mutex> 17 #include <string> 18 19 #include "unicode/udata.h" 20 win_mmap(const char * dataFile)21 static void* win_mmap(const char* dataFile) { 22 if (!dataFile) { 23 return nullptr; 24 } 25 struct FCloseWrapper { void operator()(FILE* f) { fclose(f); } }; 26 std::unique_ptr<FILE, FCloseWrapper> stream(fopen(dataFile, "rb")); 27 if (!stream) { 28 fprintf(stderr, "SkIcuLoader: datafile missing.\n"); 29 return nullptr; 30 } 31 int fileno = _fileno(stream.get()); 32 if (fileno < 0) { 33 fprintf(stderr, "SkIcuLoader: datafile fileno error.\n"); 34 return nullptr; 35 } 36 HANDLE file = (HANDLE)_get_osfhandle(fileno); 37 if ((HANDLE)INVALID_HANDLE_VALUE == file) { 38 fprintf(stderr, "SkIcuLoader: datafile handle error.\n"); 39 return nullptr; 40 } 41 struct CloseHandleWrapper { void operator()(HANDLE h) { CloseHandle(h); } }; 42 std::unique_ptr<void, CloseHandleWrapper> mmapHandle( 43 CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr)); 44 if (!mmapHandle) { 45 fprintf(stderr, "SkIcuLoader: datafile mmap error.\n"); 46 return nullptr; 47 } 48 void* addr = MapViewOfFile(mmapHandle.get(), FILE_MAP_READ, 0, 0, 0); 49 if (nullptr == addr) { 50 fprintf(stderr, "SkIcuLoader: datafile view error.\n"); 51 return nullptr; 52 } 53 return addr; 54 } 55 init_icu(void * addr)56 static bool init_icu(void* addr) { 57 UErrorCode err = U_ZERO_ERROR; 58 udata_setCommonData(addr, &err); 59 if (err != U_ZERO_ERROR) { 60 fprintf(stderr, "udata_setCommonData() returned %d.\n", (int)err); 61 return false; 62 } 63 udata_setFileAccess(UDATA_ONLY_PACKAGES, &err); 64 if (err != U_ZERO_ERROR) { 65 fprintf(stderr, "udata_setFileAccess() returned %d.\n", (int)err); 66 return false; 67 } 68 return true; 69 } 70 executable_directory()71 static std::string executable_directory() { 72 HMODULE hModule = GetModuleHandleA(NULL); 73 char path[MAX_PATH]; 74 GetModuleFileNameA(hModule, path, MAX_PATH); 75 const char* end = strrchr(path, '\\'); 76 return end ? std::string(path, end - path) : std::string(); 77 } 78 SkLoadICU()79 bool SkLoadICU() { 80 static bool good = false; 81 static std::once_flag flag; 82 std::call_once(flag, []() { 83 std::string sPath = executable_directory(); 84 sPath += "\\icudtl.dat"; 85 if (void* addr = win_mmap(sPath.c_str())) { 86 if (init_icu(addr)) { 87 good = true; 88 } 89 } 90 }); 91 return good; 92 } 93 94 #endif // defined(_WIN32) && defined(SK_USING_THIRD_PARTY_ICU) 95