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")