blob: ac7ba0c15da2b2ea2f500827b338b25168910b88 [file] [log] [blame]
Hal Canary61021922019-02-06 12:29:11 -05001// 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>
Hal Canary689334c2019-02-22 11:25:25 -050012#include <io.h>
Hal Canary61021922019-02-06 12:29:11 -050013
14#include <cstdio>
Hal Canary689334c2019-02-22 11:25:25 -050015#include <cstring>
Hal Canary61021922019-02-06 12:29:11 -050016#include <mutex>
Hal Canary689334c2019-02-22 11:25:25 -050017#include <string>
Hal Canary61021922019-02-06 12:29:11 -050018
19#include "unicode/udata.h"
20
Hal Canary689334c2019-02-22 11:25:25 -050021static 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
56static 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
71static 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}
Hal Canary61021922019-02-06 12:29:11 -050078
79bool SkLoadICU() {
80 static bool good = false;
81 static std::once_flag flag;
82 std::call_once(flag, []() {
Hal Canary689334c2019-02-22 11:25:25 -050083 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 }
Hal Canary61021922019-02-06 12:29:11 -050089 }
Hal Canary61021922019-02-06 12:29:11 -050090 });
91 return good;
92}
93
Hal Canary61021922019-02-06 12:29:11 -050094#endif // defined(_WIN32) && defined(SK_USING_THIRD_PARTY_ICU)