Skip to content

Commit 754ecbe

Browse files
authored
Add UTF-8 filename support on Windows to ktxtools (KhronosGroup#788)
Fixes KhronosGroup#781.
1 parent bd7f377 commit 754ecbe

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,9 @@ if(MSVC)
241241
# because `/W4;/WX` is returned as a single string.
242242
add_compile_options( /W4;$<$<BOOL:${KTX_WERROR}>:/WX> )
243243
add_compile_options( $<IF:$<CONFIG:Debug>,/Gz,/O2> )
244+
# Enable UTF-8 support
245+
add_compile_options( $<$<C_COMPILER_ID:MSVC>:/utf-8> )
246+
add_compile_options( $<$<CXX_COMPILER_ID:MSVC>:/utf-8> )
244247
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU"
245248
OR ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
246249
add_compile_options( -Wall -Wextra $<$<BOOL:${KTX_WERROR}>:-Werror>)
@@ -915,6 +918,7 @@ add_library( objUtil STATIC
915918
utils/sbufstream.h
916919
utils/scapp.h
917920
utils/stdafx.h
921+
utils/platform_utils.h
918922
utils/unused.h
919923
)
920924
target_include_directories(

utils/platform_utils.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2022-2023 The Khronos Group Inc.
2+
// Copyright 2022-2023 RasterGrid Kft.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#pragma once
6+
7+
#include "stdafx.h"
8+
#include <string>
9+
#include <iostream>
10+
#include <memory>
11+
#include <vector>
12+
#include <fmt/ostream.h>
13+
#include <fmt/printf.h>
14+
15+
#if defined(_WIN32)
16+
#ifndef WIN32_LEAN_AND_MEAN
17+
#define WIN32_LEAN_AND_MEAN
18+
#endif
19+
#ifndef NOMINMAX
20+
#define NOMINMAX
21+
#endif
22+
#include <windows.h>
23+
#include <shellapi.h>
24+
#endif
25+
26+
#if defined(_WIN32) && !defined(_UNICODE)
27+
// For Windows, we convert the UTF-8 path to a UTF-16 path to force using the APIs
28+
// that correctly handle unicode characters
29+
inline std::wstring DecodeUTF8Path(std::string path) {
30+
std::wstring result;
31+
int len = MultiByteToWideChar(CP_UTF8, 0, path.c_str(), static_cast<int>(path.length()), NULL, 0);
32+
if (len > 0)
33+
{
34+
result.resize(len);
35+
MultiByteToWideChar(CP_UTF8, 0, path.c_str(), static_cast<int>(path.length()), &result[0], len);
36+
}
37+
return result;
38+
}
39+
#else
40+
// For other platforms there is no need for any conversion, they support UTF-8 natively
41+
inline std::string DecodeUTF8Path(std::string path) {
42+
return path;
43+
}
44+
#endif
45+
46+
inline void InitUTF8CLI(int& argc, _TCHAR* argv[]) {
47+
#if defined(_WIN32) && !defined(_UNICODE)
48+
// Windows does not support UTF-8 argv so we have to manually acquire it
49+
static std::vector<std::unique_ptr<_TCHAR[]>> utf8Argv(argc);
50+
LPWSTR commandLine = GetCommandLineW();
51+
LPWSTR* wideArgv = CommandLineToArgvW(commandLine, &argc);
52+
for (int i = 0; i < argc; ++i) {
53+
int byteSize = WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, nullptr, 0, nullptr, nullptr);
54+
utf8Argv[i] = std::make_unique<_TCHAR[]>(byteSize);
55+
WideCharToMultiByte(CP_UTF8, 0, wideArgv[i], -1, utf8Argv[i].get(), byteSize, nullptr, nullptr);
56+
argv[i] = utf8Argv[i].get();
57+
}
58+
#else
59+
// Nothing to do for other platforms
60+
(void)argc;
61+
(void)argv;
62+
#endif
63+
}

0 commit comments

Comments
 (0)