Use FriBidi for Bidi and shaping instead of ICU

This commit is contained in:
Gymnasiast 2020-09-01 21:22:54 +02:00
parent da82144bfb
commit 751810fc24
No known key found for this signature in database
GPG key ID: DBFFF47AB2CA3EDD
2 changed files with 29 additions and 32 deletions

View file

@ -196,6 +196,8 @@ if (HAVE_DISCORD_RPC)
target_link_libraries(libopenrct2 discord-rpc)
endif()
target_link_libraries(libopenrct2 fribidi)
# Includes
target_include_directories(${PROJECT_NAME} PRIVATE ${LIBZIP_INCLUDE_DIRS})
target_include_directories(${PROJECT_NAME} PRIVATE ${PNG_INCLUDE_DIRS}

View file

@ -9,6 +9,13 @@
#include "LanguagePack.h"
extern "C" {
#include <fribidi/fribidi-bidi-types.h>
#include <fribidi/fribidi-char-sets.h>
#include <fribidi/fribidi-flags.h>
#include <fribidi/fribidi.h>
}
#include "../common.h"
#include "../core/FileStream.hpp"
#include "../core/Memory.hpp"
@ -21,14 +28,6 @@
#include <algorithm>
#include <string>
#include <vector>
#ifndef _WIN32
# include <unicode/ubidi.h>
# include <unicode/unistr.h>
# include <unicode/ushape.h>
# include <unicode/ustring.h>
# include <unicode/utf.h>
# include <unicode/utypes.h>
#endif
// Don't try to load more than language files that exceed 64 MiB
constexpr uint64_t MAX_LANGUAGE_SIZE = 64 * 1024 * 1024;
@ -650,33 +649,29 @@ private:
std::string FixRTL(std::string& input)
{
#ifdef _WIN32
return input;
#else
UErrorCode err = static_cast<UErrorCode>(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;
FriBidiChar utf32String[1024] = { 0 };
FriBidiStrIndex len = input.length() + 1;
fribidi_charset_to_unicode(FRIBIDI_CHAR_SET_UTF8, input.c_str(), len, utf32String);
icu::UnicodeString ustr = icu::UnicodeString::fromUTF8(icu::StringPiece(text2));
FriBidiStrIndex utf32len = 0;
for (; utf32len < 1024; utf32len++)
{
if (utf32String[utf32len] == 0)
{
break;
}
}
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);
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;
std::string cppstring;
shaped.toUTF8String(cppstring);
return cppstring;
#endif
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);
}
};