From 4ff77ebc358068aa8331d9654561624dcc33592a Mon Sep 17 00:00:00 2001 From: Gymnasiast Date: Sat, 5 Sep 2020 14:01:38 +0200 Subject: [PATCH] Split RTL implementations to files; add preprocessor guards --- openrct2.proj | 1 + src/openrct2/libopenrct2.vcxproj | 3 +- src/openrct2/localisation/LanguagePack.cpp | 70 +--------------------- src/openrct2/localisation/RTL.FriBidi.cpp | 63 +++++++++++++++++++ src/openrct2/localisation/RTL.ICU.cpp | 47 +++++++++++++++ src/openrct2/localisation/RTL.h | 14 +++++ test/tests/CMakeLists.txt | 2 + 7 files changed, 130 insertions(+), 70 deletions(-) create mode 100644 src/openrct2/localisation/RTL.FriBidi.cpp create mode 100644 src/openrct2/localisation/RTL.ICU.cpp create mode 100644 src/openrct2/localisation/RTL.h diff --git a/openrct2.proj b/openrct2.proj index 5cd64342d8..57eaa89507 100644 --- a/openrct2.proj +++ b/openrct2.proj @@ -22,6 +22,7 @@ /D "OPENRCT2_COMMIT_SHA1_SHORT=\"$(OPENRCT2_SHA1_SHORT)\"" $(OPENRCT2_CL_ADDITIONALOPTIONS) /D "OPENRCT2_VERSION_TAG=\"$(OPENRCT2_DESCRIBE)\"" $(OPENRCT2_CL_ADDITIONALOPTIONS) /D "USE_BREAKPAD" $(OPENRCT2_CL_ADDITIONALOPTIONS) + /D "USE_FRIBIDI" $(OPENRCT2_CL_ADDITIONALOPTIONS) $(MsBuildThisFileDirectory) $(RootDir)bin\ diff --git a/src/openrct2/libopenrct2.vcxproj b/src/openrct2/libopenrct2.vcxproj index 9e6a2d01b4..29c589ab8f 100644 --- a/src/openrct2/libopenrct2.vcxproj +++ b/src/openrct2/libopenrct2.vcxproj @@ -34,6 +34,7 @@ __ENABLE_DISCORD__;__ENABLE_LIGHTFX__;USE_BENCHMARK;%(PreprocessorDefinitions) USE_BREAKPAD;%(PreprocessorDefinitions) + USE_FRIBIDI;%(PreprocessorDefinitions) @@ -770,4 +771,4 @@ - \ No newline at end of file + diff --git a/src/openrct2/localisation/LanguagePack.cpp b/src/openrct2/localisation/LanguagePack.cpp index 81f19531e4..731c3c36ba 100644 --- a/src/openrct2/localisation/LanguagePack.cpp +++ b/src/openrct2/localisation/LanguagePack.cpp @@ -17,27 +17,12 @@ #include "../core/StringReader.hpp" #include "Language.h" #include "Localisation.h" +#include "RTL.h" #include #include #include -#ifdef _WIN32 -extern "C" { -# include -# include -# include -# include -} -#else -# include -# include -# include -# include -# include -# include -#endif - // Don't try to load more than language files that exceed 64 MiB constexpr uint64_t MAX_LANGUAGE_SIZE = 64 * 1024 * 1024; constexpr uint64_t MAX_OBJECT_OVERRIDES = 4096; @@ -655,59 +640,6 @@ private: return true; } - - std::string FixRTL(std::string& input) - { -#ifdef _WIN32 - FriBidiChar utf32String[1024] = { 0 }; - FriBidiStrIndex len = input.length() + 1; - fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, input.c_str(), len, utf32String); - - FriBidiStrIndex utf32len = 0; - for (; utf32len < 1024; utf32len++) - { - if (utf32String[utf32len] == 0) - { - break; - } - } - - FriBidiChar reorderedStr[1024] = { 0 }; - // All our strings start in LTR direction due to the "STR_0001: prefix", even fully Arabic ones. - FriBidiCharType pbase_dir = FRIBIDI_TYPE_LTR; - - fribidi_log2vis(utf32String, utf32len, &pbase_dir, reorderedStr, nullptr, nullptr, nullptr); - - char outputString[1024]; - fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, reorderedStr, len, outputString); - - return std::string(outputString); -#else - UErrorCode err = static_cast(0); - // Force a hard left-to-right at the beginning (will mess up mixed strings' word order otherwise) - std::string text2 = std::string(u8"\xE2\x80\xAA") + input; - - icu::UnicodeString ustr = icu::UnicodeString::fromUTF8(icu::StringPiece(text2)); - - int32_t length = ustr.length(); - icu::UnicodeString reordered; - icu::UnicodeString shaped; - UBiDi* bidi = ubidi_openSized(length, 0, &err); - // UBIDI_DEFAULT_LTR preserves formatting codes. - ubidi_setPara(bidi, ustr.getBuffer(), length, UBIDI_DEFAULT_LTR, nullptr, &err); - ubidi_writeReordered(bidi, reordered.getBuffer(length), length, UBIDI_DO_MIRRORING | UBIDI_REMOVE_BIDI_CONTROLS, &err); - ubidi_close(bidi); - reordered.releaseBuffer(length); - u_shapeArabic( - reordered.getBuffer(), length, shaped.getBuffer(length), length, - U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, &err); - shaped.releaseBuffer(length); - - std::string cppstring; - shaped.toUTF8String(cppstring); - return cppstring; -#endif - } }; namespace LanguagePackFactory diff --git a/src/openrct2/localisation/RTL.FriBidi.cpp b/src/openrct2/localisation/RTL.FriBidi.cpp new file mode 100644 index 0000000000..133cc09323 --- /dev/null +++ b/src/openrct2/localisation/RTL.FriBidi.cpp @@ -0,0 +1,63 @@ +/***************************************************************************** + * Copyright (c) 2014-2020 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#if defined(_WIN32) && defined(USE_FRIBIDI) +# include "RTL.h" + +# include + +extern "C" { +# include +# include +# include +# include +} + +static constexpr const uint16_t BufferLength = 1024; + +std::string FixRTL(std::string& input) +{ + FriBidiChar utf32String[BufferLength] = { 0 }; + FriBidiStrIndex len = input.length() + 1; + fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, input.c_str(), len, utf32String); + + FriBidiStrIndex utf32len = 0; + for (; utf32len < std::size(utf32String); utf32len++) + { + if (utf32String[utf32len] == 0) + { + break; + } + } + + FriBidiChar reorderedStr[BufferLength] = { 0 }; + // All our strings start in LTR direction due to the "STR_0001: prefix", even fully Arabic ones. + FriBidiCharType pbase_dir = FRIBIDI_TYPE_LTR; + + fribidi_log2vis(utf32String, utf32len, &pbase_dir, reorderedStr, nullptr, nullptr, nullptr); + + char outputString[BufferLength]; + fribidi_unicode_to_charset(FRIBIDI_CHAR_SET_UTF8, reorderedStr, len, outputString); + + return std::string(outputString); +} +#elif defined(_WIN32) +static bool hasWarned = false; + +std::string FixRTL(std::string& input) +{ + if (!hasWarned) + { + log_warning("This build of OpenRCT2 cannot properly handle right-to-left text!"); + hasWarned = true; + } + + return input; +} +#endif diff --git a/src/openrct2/localisation/RTL.ICU.cpp b/src/openrct2/localisation/RTL.ICU.cpp new file mode 100644 index 0000000000..c9a8bff41b --- /dev/null +++ b/src/openrct2/localisation/RTL.ICU.cpp @@ -0,0 +1,47 @@ +/***************************************************************************** + * Copyright (c) 2014-2020 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#ifndef _WIN32 +# include "RTL.h" + +# include +# include +# include +# include +# include +# include +# include + +std::string FixRTL(std::string& input) +{ + UErrorCode err = static_cast(0); + // Force a hard left-to-right at the beginning (will mess up mixed strings' word order otherwise) + std::string text2 = std::string(u8"\xE2\x80\xAA") + input; + + icu::UnicodeString ustr = icu::UnicodeString::fromUTF8(icu::StringPiece(text2)); + + int32_t length = ustr.length(); + icu::UnicodeString reordered; + icu::UnicodeString shaped; + UBiDi* bidi = ubidi_openSized(length, 0, &err); + // UBIDI_DEFAULT_LTR preserves formatting codes. + ubidi_setPara(bidi, ustr.getBuffer(), length, UBIDI_DEFAULT_LTR, nullptr, &err); + ubidi_writeReordered(bidi, reordered.getBuffer(length), length, UBIDI_DO_MIRRORING | UBIDI_REMOVE_BIDI_CONTROLS, &err); + ubidi_close(bidi); + reordered.releaseBuffer(length); + u_shapeArabic( + reordered.getBuffer(), length, shaped.getBuffer(length), length, + U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR | U_SHAPE_TEXT_DIRECTION_VISUAL_LTR, &err); + shaped.releaseBuffer(length); + + std::string cppstring; + shaped.toUTF8String(cppstring); + return cppstring; +} +#endif diff --git a/src/openrct2/localisation/RTL.h b/src/openrct2/localisation/RTL.h new file mode 100644 index 0000000000..8801f407cc --- /dev/null +++ b/src/openrct2/localisation/RTL.h @@ -0,0 +1,14 @@ +/***************************************************************************** + * Copyright (c) 2014-2020 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include + +std::string FixRTL(std::string& input); diff --git a/test/tests/CMakeLists.txt b/test/tests/CMakeLists.txt index bbba5a79a0..bd89e80423 100644 --- a/test/tests/CMakeLists.txt +++ b/test/tests/CMakeLists.txt @@ -120,6 +120,8 @@ add_test(NAME sawyercoding COMMAND test_sawyercoding) set(LANGUAGEPACK_TEST_SOURCES "${CMAKE_CURRENT_LIST_DIR}/LanguagePackTest.cpp" "${ROOT_DIR}/src/openrct2/localisation/LanguagePack.cpp" + "${ROOT_DIR}/src/openrct2/localisation/RTL.FriBidi.cpp" + "${ROOT_DIR}/src/openrct2/localisation/RTL.ICU.cpp" ) add_executable(test_languagepack ${LANGUAGEPACK_TEST_SOURCES}) if (UNIX AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "BSD")