diff --git a/coding/transliteration.cpp b/coding/transliteration.cpp index 84cc8fca75..3c391f396a 100644 --- a/coding/transliteration.cpp +++ b/coding/transliteration.cpp @@ -2,6 +2,7 @@ #include "coding/multilang_utf8_string.hpp" #include "base/logging.hpp" +#include "base/string_utils.hpp" #include "3party/icu/common/unicode/uclean.h" #include "3party/icu/common/unicode/unistr.h" @@ -60,7 +61,7 @@ void Transliteration::Init(std::string const & icuDataDir) bool Transliteration::Transliterate(std::string const & str, int8_t langCode, std::string & out) const { - if (str.empty()) + if (str.empty() || strings::IsASCIIString(str)) return false; std::string transliteratorId(StringUtf8Multilang::GetTransliteratorIdByCode(langCode)); diff --git a/data/copyright.html b/data/copyright.html index 684db76d53..da8634aad7 100644 --- a/data/copyright.html +++ b/data/copyright.html @@ -144,9 +144,6 @@ © 2014 Google Inc.; BSD License; MIT License; Apache License -
  • GNU FriBidi
    - © Behdad Esfahbod, Dov Grobgeld, Roozbeh Pournader; LGPL
  • -
  • GLM
    © 2005–2014 G-Truc Creation; MIT License
  • diff --git a/drape/CMakeLists.txt b/drape/CMakeLists.txt index 4dd9c32e78..fba55fc05c 100644 --- a/drape/CMakeLists.txt +++ b/drape/CMakeLists.txt @@ -9,9 +9,13 @@ execute_process( shader_def ) +add_definitions(-DU_DISABLE_RENAMING) + include_directories( ${OMIM_ROOT}/3party/freetype/include ${OMIM_ROOT}/3party/glm + ${OMIM_ROOT}/3party/icu/common + ${OMIM_ROOT}/3party/icu/i18n ) set( diff --git a/drape/drape.pro b/drape/drape.pro index 9d0247327b..26cc43a447 100644 --- a/drape/drape.pro +++ b/drape/drape.pro @@ -1,6 +1,8 @@ TARGET = drape TEMPLATE = lib CONFIG += staticlib warn_on +INCLUDEPATH += ../3party/icu/common ../3party/icu/i18n +DEFINES += U_DISABLE_RENAMING ROOT_DIR = .. SHADER_COMPILE_ARGS = $$PWD/shaders shader_index.txt shader_def diff --git a/drape/drape_tests/drape_tests.pro b/drape/drape_tests/drape_tests.pro index 1c6ed84c46..3d44b76b34 100644 --- a/drape/drape_tests/drape_tests.pro +++ b/drape/drape_tests/drape_tests.pro @@ -2,7 +2,8 @@ TARGET = drape_tests CONFIG += console warn_on CONFIG -= app_bundle TEMPLATE = app -DEFINES += OGL_TEST_ENABLED GTEST_DONT_DEFINE_TEST COMPILER_TESTS +INCLUDEPATH += ../../3party/icu/common ../../3party/icu/i18n +DEFINES += OGL_TEST_ENABLED GTEST_DONT_DEFINE_TEST COMPILER_TESTS U_DISABLE_RENAMING ROOT_DIR = ../.. DEPENDENCIES = qt_tstfrm indexer platform coding geometry base gmock freetype fribidi expat stats_client stb_image sdf_image icu diff --git a/drape/drape_tests/fribidi_tests.cpp b/drape/drape_tests/fribidi_tests.cpp index 85061113d8..50030e622c 100644 --- a/drape/drape_tests/fribidi_tests.cpp +++ b/drape/drape_tests/fribidi_tests.cpp @@ -7,7 +7,7 @@ UNIT_TEST(FribidiDirection) { string base = "\u0686\u0631\u0645\u0647\u064A\u0646"; strings::UniString in = strings::MakeUniString(base); - strings::UniString out1 = fribidi::log2vis(in); + strings::UniString out1 = bidi::log2vis(in); string out = "\uFEE6\uFEF4\uFEEC\uFEE3\uFEAE\uFB7C"; strings::UniString out2 = strings::MakeUniString(out); bool eq = out1 == out2; diff --git a/drape/fribidi.cpp b/drape/fribidi.cpp index df1f116ebe..8f5e534cdf 100644 --- a/drape/fribidi.cpp +++ b/drape/fribidi.cpp @@ -1,13 +1,60 @@ -#include "base/string_utils.hpp" +#include "drape/fribidi.hpp" + +#include "3party/icu/common/unicode/ubidi.h" +#include "3party/icu/common/unicode/unistr.h" +#include "3party/icu/common/unicode/ushape.h" #include "3party/fribidi/lib/fribidi.h" - #include "std/mutex.hpp" -namespace fribidi +namespace bidi { strings::UniString log2vis(strings::UniString const & str) +{ + std::string str8 = strings::ToUtf8(str); + if (strings::IsASCIIString(str8)) + return str; + + UBiDi * bidi = ubidi_open(); + UErrorCode errorCode = U_ZERO_ERROR; + + UnicodeString ustr(str8.c_str()); + ubidi_setPara(bidi, ustr.getTerminatedBuffer(), ustr.length(), UBIDI_DEFAULT_LTR, nullptr, &errorCode); + + UBiDiDirection const direction = ubidi_getDirection(bidi); + if (direction == UBIDI_LTR || direction == UBIDI_NEUTRAL) + { + ubidi_close(bidi); + return str; + } + + std::vector buff(ustr.length() * 2, 0); + + u_shapeArabic(ustr.getTerminatedBuffer(), ustr.length(), buff.data(), static_cast(buff.size()), + U_SHAPE_LETTERS_SHAPE_TASHKEEL_ISOLATED, &errorCode); + if (errorCode != U_ZERO_ERROR) + return str; + + UnicodeString shaped(buff.data()); + + ubidi_setPara(bidi, shaped.getTerminatedBuffer(), shaped.length(), direction, nullptr, &errorCode); + + ubidi_writeReordered(bidi, buff.data(), static_cast(buff.size()), 0, &errorCode); + if (errorCode != U_ZERO_ERROR) + return str; + + UnicodeString reordered(buff.data()); + + ubidi_close(bidi); + + std::string out; + reordered.toUTF8String(out); + + return strings::MakeUniString(out); +} + +strings::UniString log2vis_old(strings::UniString const & str) { static mutex log2visMutex; diff --git a/drape/fribidi.hpp b/drape/fribidi.hpp index b3db34601d..9adb9fde5e 100644 --- a/drape/fribidi.hpp +++ b/drape/fribidi.hpp @@ -2,11 +2,10 @@ #include "base/string_utils.hpp" -#include "3party/fribidi/lib/fribidi.h" - -namespace fribidi +namespace bidi { strings::UniString log2vis(strings::UniString const & str); +strings::UniString log2vis_old(strings::UniString const & str); } diff --git a/drape_frontend/gui/gui_text.cpp b/drape_frontend/gui/gui_text.cpp index b28c1559a1..bc387f5cc1 100644 --- a/drape_frontend/gui/gui_text.cpp +++ b/drape_frontend/gui/gui_text.cpp @@ -118,7 +118,7 @@ void StaticLabel::CacheStaticText(string const & text, char const * delim, dp::TextureManager::TMultilineText textParts; strings::Tokenize(text, delim, [&textParts](string const & part) { - textParts.push_back(fribidi::log2vis(strings::MakeUniString(part))); + textParts.push_back(bidi::log2vis(strings::MakeUniString(part))); }); ASSERT(!textParts.empty(), ()); @@ -370,7 +370,7 @@ void MutableLabel::SetText(LabelResult & result, string text) const if (text.size() > m_maxLength) text = text.erase(m_maxLength - 3) + "..."; - strings::UniString uniText = fribidi::log2vis(strings::MakeUniString(text)); + strings::UniString uniText = bidi::log2vis(strings::MakeUniString(text)); float maxHeight = 0.0f; float length = 0.0f; diff --git a/drape_frontend/text_layout.cpp b/drape_frontend/text_layout.cpp index 6b58c5f198..7495ae3a4a 100644 --- a/drape_frontend/text_layout.cpp +++ b/drape_frontend/text_layout.cpp @@ -337,7 +337,7 @@ strings::UniString const & TextLayout::GetText() const StraightTextLayout::StraightTextLayout(strings::UniString const & text, float fontSize, bool isSdf, ref_ptr textures, dp::Anchor anchor) { - strings::UniString visibleText = fribidi::log2vis(text); + strings::UniString visibleText = bidi::log2vis(text); buffer_vector delimIndexes; if (visibleText == text) SplitText(visibleText, delimIndexes); @@ -393,7 +393,7 @@ PathTextLayout::PathTextLayout(m2::PointD const & tileCenter, strings::UniString float fontSize, bool isSdf, ref_ptr textures) : m_tileCenter(tileCenter) { - Init(fribidi::log2vis(text), fontSize, isSdf, textures); + Init(bidi::log2vis(text), fontSize, isSdf, textures); } void PathTextLayout::CacheStaticGeometry(dp::TextureManager::ColorRegion const & colorRegion, diff --git a/drape_frontend/watch/cpu_drawer.cpp b/drape_frontend/watch/cpu_drawer.cpp index 61dabb5163..0e60c859aa 100644 --- a/drape_frontend/watch/cpu_drawer.cpp +++ b/drape_frontend/watch/cpu_drawer.cpp @@ -27,13 +27,12 @@ void CorrectFont(dp::FontDecl & font) strings::UniString PreProcessText(string const & text) { - strings::UniString logText = strings::MakeUniString(text); - strings::UniString visText = df::watch::GlyphCache::log2vis(logText); + // Warning! This code processes text as left-to-right text + // and doesn't reorder right-to-left text. To support right-to-left text + // bidi algorithm should be applied. + strings::UniString visText = strings::MakeUniString(text); char const * delims = " \n\t"; - if (logText != visText) - return visText; - size_t count = visText.size(); if (count > 15) { @@ -637,7 +636,10 @@ void CPUDrawer::CallTextRendererFn(TextShape const * shape, TRoadNumberRendererC { string const & text = GetInfo(shape->m_geomID, m_roadNames); - fn(shape->m_position, shape->m_anchor, m_roadNumberFont, GlyphCache::log2vis(strings::MakeUniString(text))); + // Warning! This code processes text as left-to-right text + // and doesn't reorder right-to-left text. To support right-to-left text + // bidi algorithm should be applied. + fn(shape->m_position, shape->m_anchor, m_roadNumberFont, strings::MakeUniString(text)); } void CPUDrawer::CallTextRendererFn(ComplexShape const * shape, TPathTextRendererCall const & fn) diff --git a/drape_frontend/watch/glyph_cache.cpp b/drape_frontend/watch/glyph_cache.cpp index 5dd91bde1d..7d40582778 100644 --- a/drape_frontend/watch/glyph_cache.cpp +++ b/drape_frontend/watch/glyph_cache.cpp @@ -98,22 +98,5 @@ double GlyphCache::getTextLength(double fontSize, string const & text) return len; } -threads::Mutex GlyphCache::s_fribidiMutex; - -strings::UniString GlyphCache::log2vis(strings::UniString const & str) -{ - size_t const count = str.size(); - if (count == 0) - return str; - - strings::UniString res(count); - - //FriBidiEnv env; - threads::MutexGuard g(s_fribidiMutex); - FriBidiParType dir = FRIBIDI_PAR_LTR; // requested base direction - fribidi_log2vis(&str[0], static_cast(count), &dir, &res[0], 0, 0, 0); - return res; -} - } } diff --git a/drape_frontend/watch/glyph_cache.hpp b/drape_frontend/watch/glyph_cache.hpp index 9864c6bae0..7df1ad2f74 100644 --- a/drape_frontend/watch/glyph_cache.hpp +++ b/drape_frontend/watch/glyph_cache.hpp @@ -94,8 +94,6 @@ public: GlyphMetrics const getGlyphMetrics(GlyphKey const & key); double getTextLength(double fontSize, string const & text); - - static strings::UniString log2vis(strings::UniString const & str); }; }