Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Utf-8/unicode support in legacy tools and lib. #800

Merged
merged 19 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ if(WIN32)
# generators (like Visual Studio) to take the exact path and not
# change it.
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY $<1:${KTX_BUILD_DIR}/$<CONFIG>>)
elseif(APPLE)
elseif(APPLE OR LINUX)
if(NOT IOS)
# Set a common RUNTIME_OUTPUT_DIR and LIBRARY_OUTPUT_DIR for all targets,
# so that INSTALL RPATH is functional in build directory as well.
Expand Down
6 changes: 1 addition & 5 deletions lib/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -1251,11 +1251,7 @@ ktxPrintKTX2InfoJSONForNamedFile(const char* const filename, ktx_uint32_t base_i
{
FILE* file = NULL;

#ifdef _WIN32
fopen_s(&file, filename, "rb");
#else
file = fopen(filename, "rb");
#endif
file = ktxFOpenUTF8(filename, "rb");

if (!file)
return KTX_FILE_OPEN_FAILED;
Expand Down
46 changes: 46 additions & 0 deletions lib/ktxint.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,52 @@ KTX_error_code ktxUncompressZLIBInt(unsigned char* pDest,

KTX_error_code printKTX2Info2(ktxStream* src, KTX_header2* header);

/*
* fopen a file identified by a UTF-8 path.
*/
#if defined(_WIN32)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <assert.h>
#include <windows.h>
#include <shellapi.h>
#include <stdlib.h>

// For Windows, we convert the UTF-8 path and mode to UTF-16 path and use _wfopen
// which correctly handles unicode characters.
static inline FILE* ktxFOpenUTF8(char const* path, char const* mode) {
int wpLen = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
int wmLen = MultiByteToWideChar(CP_UTF8, 0, mode, -1, NULL, 0);
FILE* fp = NULL;
if (wpLen > 0 && wmLen > 0)
{
wchar_t* wpath = (wchar_t*)malloc(wpLen * sizeof(wchar_t));
wchar_t* wmode = (wchar_t*)malloc(wmLen * sizeof(wchar_t));
MultiByteToWideChar(CP_UTF8, 0, path, -1, wpath, wpLen);
MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, wmLen);
// Returned errmo_t value is also set in the global errno.
// Apps use that for error detail as libktx only returns
// KTX_FILE_OPEN_FAILED.
(void)_wfopen_s(&fp, wpath, wmode);
free(wpath);
free(wmode);
return fp;
} else {
assert(KTX_FALSE && "ktxFOpenUTF8 called with zero length path or mode.");
return NULL;
}
}
#else
// For other platforms there is no need for any conversion, they support UTF-8 natively
static inline FILE* ktxFOpenUTF8(char const* path, char const* mode) {
return fopen(path, mode);
}
#endif

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion lib/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ ktxTexture_CreateFromNamedFile(const char* const filename,
if (filename == NULL || newTex == NULL)
return KTX_INVALID_VALUE;

file = fopen(filename, "rb");
file = ktxFOpenUTF8(filename, "rb");
if (!file)
return KTX_FILE_OPEN_FAILED;

Expand Down
8 changes: 7 additions & 1 deletion lib/texture1.c
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,9 @@ ktxTexture1_constructFromStdioStream(ktxTexture1* This, FILE* stdioStream,
* @memberof ktxTexture1 @private
* @brief Construct a ktxTexture1 from a named KTX file.
*
* The file name must be encoded in utf-8. On Windows convert unicode names
* to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling.
*
* See ktxTextureInt_constructFromStream for details.
*
* @param[in] This pointer to a ktxTextureInt-sized block of memory to
Expand All @@ -484,7 +487,7 @@ ktxTexture1_constructFromNamedFile(ktxTexture1* This,
if (This == NULL || filename == NULL)
return KTX_INVALID_VALUE;

file = fopen(filename, "rb");
file = ktxFOpenUTF8(filename, "rb");
if (!file)
return KTX_FILE_OPEN_FAILED;

Expand Down Expand Up @@ -681,6 +684,9 @@ ktxTexture1_CreateFromStdioStream(FILE* stdioStream,
* The address of a newly created texture reflecting the contents of the
* file is written to the location pointed at by @p newTex.
*
* The file name must be encoded in utf-8. On Windows convert unicode names
* to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling.
*
* The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
* if the ktxTexture1 is ultimately to be uploaded to OpenGL or Vulkan. This
* will minimize memory usage by allowing, for example, loading the images
Expand Down
8 changes: 7 additions & 1 deletion lib/texture2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,9 @@ ktxTexture2_constructFromStdioStream(ktxTexture2* This, FILE* stdioStream,
* @~English
* @brief Construct a ktxTexture from a named KTX file.
*
* The file name must be encoded in utf-8. On Windows convert unicode names
* to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling.
*
* See ktxTextureInt_constructFromStream for details.
*
* @param[in] This pointer to a ktxTextureInt-sized block of memory to
Expand All @@ -1127,7 +1130,7 @@ ktxTexture2_constructFromNamedFile(ktxTexture2* This,
if (This == NULL || filename == NULL)
return KTX_INVALID_VALUE;

file = fopen(filename, "rb");
file = ktxFOpenUTF8(filename, "rb");
if (!file)
return KTX_FILE_OPEN_FAILED;

Expand Down Expand Up @@ -1378,6 +1381,9 @@ ktxTexture2_CreateFromStdioStream(FILE* stdioStream,
* The address of a newly created ktxTexture2 reflecting the contents of the
* file is written to the location pointed at by @p newTex.
*
* The file name must be encoded in utf-8. On Windows convert unicode names
* to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling.
*
* The create flag KTX_TEXTURE_CREATE_LOAD_IMAGE_DATA_BIT should not be set,
* if the ktxTexture is ultimately to be uploaded to OpenGL or Vulkan. This
* will minimize memory usage by allowing, for example, loading the images
Expand Down
10 changes: 8 additions & 2 deletions lib/writer1.c
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,9 @@ ktxTexture1_WriteToStdioStream(ktxTexture1* This, FILE* dstsstr)
* @~English
* @brief Write a ktxTexture object to a named file in KTX format.
*
* The file name must be encoded in utf-8. On Windows convert unicode names
* to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling.
*
* @param[in] This pointer to the target ktxTexture object.
* @param[in] dstname destination file name.
*
Expand All @@ -422,7 +425,7 @@ ktxTexture1_WriteToNamedFile(ktxTexture1* This, const char* const dstname)
if (!This)
return KTX_INVALID_VALUE;

dst = fopen(dstname, "wb");
dst = ktxFOpenUTF8(dstname, "wb");
if (dst) {
result = ktxTexture1_WriteToStdioStream(This, dst);
fclose(dst);
Expand Down Expand Up @@ -842,6 +845,9 @@ ktxTexture1_WriteKTX2ToStdioStream(ktxTexture1* This, FILE* dstsstr)
* @~English
* @brief Write a ktxTexture object to a named file in KTX2 format.
*
* The file name must be encoded in utf-8. On Windows convert unicode names
* to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling.
*
* Callers are strongly urged to include a KTXwriter item in the texture's metadata.
* It can be added by code, similar to the following, prior to calling this
* function.
Expand Down Expand Up @@ -878,7 +884,7 @@ ktxTexture1_WriteKTX2ToNamedFile(ktxTexture1* This, const char* const dstname)
if (!This)
return KTX_INVALID_VALUE;

dst = fopen(dstname, "wb");
dst = ktxFOpenUTF8(dstname, "wb");
if (dst) {
result = ktxTexture1_WriteKTX2ToStdioStream(This, dst);
fclose(dst);
Expand Down
5 changes: 4 additions & 1 deletion lib/writer2.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,6 +632,9 @@ ktxTexture2_WriteToStdioStream(ktxTexture2* This, FILE* dstsstr)
* @~English
* @brief Write a ktxTexture object to a named file in KTX format.
*
* The file name must be encoded in utf-8. On Windows convert unicode names
* to utf-8 with @c WideCharToMultiByte(CP_UTF8, ...) before calling.
*
* Callers are strongly urged to include a KTXwriter item in the texture's metadata.
* It can be added by code, similar to the following, prior to calling this
* function.
Expand Down Expand Up @@ -668,7 +671,7 @@ ktxTexture2_WriteToNamedFile(ktxTexture2* This, const char* const dstname)
if (!This)
return KTX_INVALID_VALUE;

dst = fopen(dstname, "wb");
dst = ktxFOpenUTF8(dstname, "wb");
if (dst) {
result = ktxTexture2_WriteToStdioStream(This, dst);
fclose(dst);
Expand Down
12 changes: 12 additions & 0 deletions tests/ktx2ktx2-tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,15 @@ cnvrtcmpktx( 2d-bc2 pattern_02_bc2.ktx2 pattern_02_bc2.ktx "-f" )
cnvrtcmpktx( 2d-array-astc texturearray_astc_8x8_unorm.ktx2 texturearray_astc_8x8_unorm.ktx "-f" )

cnvrtcmpktx_implied_out( 2d-bc2 pattern_02_bc2 "-f" )

cnvrtcmpktx( unicode-file-hu hűtő.ktx2 hűtő.ktx "-f" )
cnvrtcmpktx( unicode-file-jp テクスチャ.ktx2 テクスチャ.ktx "-f" )
cnvrtcmpktx( unicode-file-ar نَسِيج.ktx2 نَسِيج.ktx "-f" )
cnvrtcmpktx( unicode-file-zh 质地.ktx2 质地.ktx "-f" )
cnvrtcmpktx( unicode-file-ko 조직.ktx2 조직.ktx "-f" )

cnvrtcmpktx_implied_out( unicode-file-hu hűtő "-f" )
cnvrtcmpktx_implied_out( unicode-file-jp テクスチャ "-f" )
cnvrtcmpktx_implied_out( unicode-file-ar نَسِيج "-f" )
cnvrtcmpktx_implied_out( unicode-file-zh 质地 "-f" )
cnvrtcmpktx_implied_out( unicode-file-ko 조직 "-f" )
10 changes: 10 additions & 0 deletions tests/ktxsc-tests.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,13 @@ endfunction()
sccmpktx( zcmp-cubemap skybox_zstd.ktx2 skybox.ktx2 "--zcmp 5" )
sccmpktxinplacecurdir( zcmp-cubemap skybox_zstd.ktx2 skybox.ktx2 "--zcmp 5" )
sccmpktxinplacediffdir( zcmp_cubemap skybox_zstd.ktx2 skybox.ktx2 "--zcmp 5" )
sccmpktxinplacecurdir( unicode-file-hu hűtő_zstd.ktx2 hűtő.ktx2 "--zcmp 5" )
sccmpktxinplacecurdir( unicode-file-jp テクスチャ_zstd.ktx2 テクスチャ.ktx2 "--zcmp 5" )
sccmpktxinplacecurdir( unicode-file-ar نَسِيج_zstd.ktx2 نَسِيج.ktx2 "--zcmp 5" )
sccmpktxinplacecurdir( unicode-file-zh 质地_zstd.ktx2 质地.ktx2 "--zcmp 5" )
sccmpktxinplacecurdir( unicode-file-ko 조직_zstd.ktx2 조직.ktx2 "--zcmp 5" )
sccmpktxinplacediffdir( unicode-file-hu hűtő_zstd.ktx2 hűtő.ktx2 "--zcmp 5" )
sccmpktxinplacediffdir( unicode-file-jp テクスチャ_zstd.ktx2 テクスチャ.ktx2 "--zcmp 5" )
sccmpktxinplacediffdir( unicode-file-ar نَسِيج_zstd.ktx2 نَسِيج.ktx2 "--zcmp 5" )
sccmpktxinplacediffdir( unicode-file-zh 质地_zstd.ktx2 质地.ktx2 "--zcmp 5" )
sccmpktxinplacediffdir( unicode-file-ko 조직_zstd.ktx2 조직.ktx2 "--zcmp 5" )
2 changes: 2 additions & 0 deletions tests/loadtests/appfwSDL/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <vector>
#include <stdio.h>
#include "AppBaseSDL.h"
#include "platform_utils.h"
#if defined(EMSCRIPTEN)
#include <emscripten.h>
#endif
Expand Down Expand Up @@ -55,6 +56,7 @@ main(int argc, char* argv[])
}
atexit(SDL_Quit);

InitUTF8CLI(argc, argv);
AppBaseSDL::Args args(argv, argv+argc);

if (!theApp->initialize(args))
Expand Down
2 changes: 1 addition & 1 deletion tests/loadtests/common/TranscodeTargetStrToFmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "TranscodeTargetStrToFmt.h"

ktx_transcode_fmt_e
TranscodeTargetStrToFmt(_tstring format)
TranscodeTargetStrToFmt(std::string format)
{
if (!format.compare("ETC1_RGB"))
return KTX_TTF_ETC1_RGB;
Expand Down
10 changes: 1 addition & 9 deletions tests/loadtests/common/TranscodeTargetStrToFmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,6 @@

#include <string>

#if !defined(_tstring)
#if defined(_UNICODE)
#define _tstring std::wstring
#else
#define _tstring std::string
#endif
#endif

ktx_transcode_fmt_e TranscodeTargetStrToFmt(_tstring format);
ktx_transcode_fmt_e TranscodeTargetStrToFmt(std::string format);

#endif /* _TRANSCODE_TARGET_STR_TO_FMT_ */
3 changes: 2 additions & 1 deletion tests/loadtests/common/ltexceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#include <stdexcept>
#include <string>

#define OUT_OF_HOST_MEMORY -1
#define OUT_OF_DEVICE_MEMORY -2
Expand All @@ -27,7 +28,7 @@ class bad_vulkan_alloc : public std::bad_alloc {
if (which == FRAGMENTED_POOL) {
message << "Pool fragmented when allocating for " << _message << ".";
} else {
std::string memtype;
std::string memtype;
switch (which) {
case OUT_OF_HOST_MEMORY: memtype = "host"; break;
case OUT_OF_DEVICE_MEMORY: memtype = "device"; break;
Expand Down
4 changes: 2 additions & 2 deletions tests/loadtests/glloadtests/shader-based/EncodeTexture.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ class EncodeTexture : public GL3LoadTestSample {
bool bInitialized;
ktx_transcode_fmt_e transcodeTarget;
enum encode_fmt_e { EF_ASTC = 1, EF_ETC1S = 2, EF_UASTC = 3 };
friend ostream& operator<<(ostream& os, encode_fmt_e format);
friend std::ostream& operator<<(std::ostream& os, encode_fmt_e format);
encode_fmt_e encodeTarget;
};

inline ostream& operator<<(ostream& os, EncodeTexture::encode_fmt_e format)
inline std::ostream& operator<<(std::ostream& os, EncodeTexture::encode_fmt_e format)
{
switch (format) {
case EncodeTexture::EF_ASTC:
Expand Down
11 changes: 6 additions & 5 deletions tests/loadtests/glloadtests/shader-based/InstancedSampleBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
* @author Mark Callow, www.edgewise-consulting.com.
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
Expand All @@ -34,6 +33,8 @@

#define member_size(type, member) sizeof(((type *)0)->member)

using namespace std;

const GLchar* InstancedSampleBase::pszInstancingFsDeclarations =
"precision mediump float;\n"

Expand Down Expand Up @@ -95,7 +96,7 @@ const GLchar* InstancedSampleBase::pszInstancingVsDeclarations =
*/
InstancedSampleBase::InstancedSampleBase(uint32_t width, uint32_t height,
const char* const szArgs,
const std::string sBasePath)
const string sBasePath)
: GL3LoadTestSample(width, height, szArgs, sBasePath),
texUnit(GL_TEXTURE0), uniformBufferBindId(0),
bInitialized(false)
Expand All @@ -113,7 +114,7 @@ InstancedSampleBase::InstancedSampleBase(uint32_t width, uint32_t height,
KTX_error_code ktxresult;
ktxTexture* kTexture;
GLenum glerror;
std::string ktxfilepath = externalFile ? ktxfilename
string ktxfilepath = externalFile ? ktxfilename
: getAssetPath() + ktxfilename;
ktxresult =
ktxTexture_CreateFromNamedFile(ktxfilepath.c_str(),
Expand Down Expand Up @@ -208,7 +209,7 @@ InstancedSampleBase::run(uint32_t /*msTicks*/)
//===================================================================

void
InstancedSampleBase::processArgs(std::string sArgs)
InstancedSampleBase::processArgs(string sArgs)
{
// Options descriptor
struct argparser::option longopts[] = {
Expand Down Expand Up @@ -436,7 +437,7 @@ InstancedSampleBase::prepareProgram(ShaderSource& fs, ShaderSource& vs)
ssDefine << "#define INSTANCE_COUNT " << instanceCount << "U" << endl;
// str().c_str() doesn't work because str goes outof scope immediately.
// Hence this 2 step process.
std::string sDefine = ssDefine.str();
string sDefine = ssDefine.str();
vs.insert(vs.begin(), sDefine.c_str());
makeShader(GL_VERTEX_SHADER, vs, &gnInstancingVs);
makeShader(GL_FRAGMENT_SHADER, fs, &gnInstancingFs);
Expand Down
5 changes: 2 additions & 3 deletions tests/loadtests/glloadtests/utils/GLMeshLoader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
#include <map>
#include <stdexcept>
#include <vector>
using namespace std;

#ifdef _WIN32
#include <windows.h>
Expand Down Expand Up @@ -211,7 +210,7 @@ class GLMeshLoader {
std::stringstream message;

message << " Import via ASSIMP from\"" << filename << "\" failed. "
<< importer.GetErrorString() << endl;
<< importer.GetErrorString() << std::endl;
throw std::runtime_error(message.str());
}

Expand Down Expand Up @@ -316,7 +315,7 @@ class GLMeshLoader {
}

void CreateBuffers(glMeshLoader::MeshBuffer& meshBuffer,
vector<glMeshLoader::VertexLayout> layout,
std::vector<glMeshLoader::VertexLayout> layout,
float scale)
{
std::vector<float> vertexBuffer;
Expand Down
3 changes: 3 additions & 0 deletions tests/srcimages/hűtő.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions tests/srcimages/نَسِيج.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions tests/srcimages/テクスチャ.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions tests/srcimages/质地.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading