Added new realization of right-to-left text reordering with BiDi algorithm from ICU library.

This commit is contained in:
Daria Volvenkova 2017-04-19 20:23:56 +03:00 committed by Sergey Yershov
parent 2ae9a8d2d0
commit 6aa1e301b5
13 changed files with 75 additions and 41 deletions

View file

@ -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));

View file

@ -144,9 +144,6 @@
&copy; 2014 Google Inc.; <a href="#bsd3-license" class="license">BSD License;</a> <a href="#mit-license" class="license">MIT License;</a>
<a href="#apache2-license" class="license">Apache License</a></li>
<li><a href="http://www.fribidi.org/">GNU FriBidi</a><br>
&copy; Behdad Esfahbod, Dov Grobgeld, Roozbeh Pournader; <a href="#lgpl21-license" class="license">LGPL</a></li>
<li><a href="http://www.g-truc.net/project-0016.html">GLM</a><br>
&copy; 2005&ndash;2014 G-Truc Creation; <a href="#mit-license" class="license">MIT License</a></li>

View file

@ -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(

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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<UChar> buff(ustr.length() * 2, 0);
u_shapeArabic(ustr.getTerminatedBuffer(), ustr.length(), buff.data(), static_cast<uint32_t>(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<uint32_t>(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;

View file

@ -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);
}

View file

@ -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;

View file

@ -337,7 +337,7 @@ strings::UniString const & TextLayout::GetText() const
StraightTextLayout::StraightTextLayout(strings::UniString const & text, float fontSize, bool isSdf,
ref_ptr<dp::TextureManager> textures, dp::Anchor anchor)
{
strings::UniString visibleText = fribidi::log2vis(text);
strings::UniString visibleText = bidi::log2vis(text);
buffer_vector<size_t, 2> 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<dp::TextureManager> 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,

View file

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

View file

@ -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<int>(count), &dir, &res[0], 0, 0, 0);
return res;
}
}
}

View file

@ -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);
};
}