From 1c517c3d7763c2f843a565577e8a4163bd839929 Mon Sep 17 00:00:00 2001 From: Viktor Govako Date: Tue, 31 Aug 2021 21:32:57 +0300 Subject: [PATCH] [drape] Replace > 0xFFFF unicode chars with spaces for valid string drawing. Signed-off-by: Viktor Govako --- drape/bidi.cpp | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/drape/bidi.cpp b/drape/bidi.cpp index 9a6b2fb2c5..0c260c75b2 100644 --- a/drape/bidi.cpp +++ b/drape/bidi.cpp @@ -11,23 +11,47 @@ namespace bidi { -strings::UniString log2vis(strings::UniString const & str) +using StringT = strings::UniString; + +StringT log2vis(StringT const & str) { uint32_t const usize = static_cast(str.size()); buffer_vector ustr(usize); bool isAscii = true; + bool hasExtendedChars = false; for (uint32_t i = 0; i < usize; ++i) { auto const c = str[i]; - assert(c <= 0xFFFF); if (c >= 0x80) isAscii = false; - ustr[i] = c; + + // As an example of extended chars: https://www.openstreetmap.org/node/5680098021 + if (c > 0xFFFF) + { + hasExtendedChars = true; + ustr[i] = ' '; + } + else + ustr[i] = c; } if (isAscii) return str; + // Remove non-drawable chars if any, or drape will not draw a string otherwise. + StringT out; + auto const ResultString = [&str, &out, hasExtendedChars]() -> StringT const & + { + if (hasExtendedChars) + { + out = str; + out.erase_if([](strings::UniChar c) { return c > 0xFFFF; }); + return out; + } + else + return str; + }; + UBiDi * bidi = ubidi_open(); SCOPE_GUARD(closeBidi, [bidi]() { ubidi_close(bidi); }); @@ -37,7 +61,7 @@ strings::UniString log2vis(strings::UniString const & str) UBiDiDirection const direction = ubidi_getDirection(bidi); if (direction == UBIDI_LTR || direction == UBIDI_NEUTRAL) - return str; + return ResultString(); uint32_t const buffSize = usize * 2; buffer_vector buff(buffSize, 0); @@ -47,7 +71,7 @@ strings::UniString log2vis(strings::UniString const & str) if (errorCode != U_ZERO_ERROR) { LOG(LWARNING, ("u_shapeArabic failed, icu error:", errorCode)); - return str; + return ResultString(); } icu::UnicodeString shaped(buff.data()); @@ -57,10 +81,9 @@ strings::UniString log2vis(strings::UniString const & str) if (errorCode != U_ZERO_ERROR) { LOG(LWARNING, ("ubidi_writeReordered failed, icu error:", errorCode)); - return str; + return ResultString(); } - strings::UniString out; out.reserve(buffSize); for (uint32_t i = 0; i < buffSize; ++i) { @@ -72,9 +95,9 @@ strings::UniString log2vis(strings::UniString const & str) return out; } -strings::UniString log2vis(std::string const & utf8) +StringT log2vis(std::string const & utf8) { - auto const uni = strings::MakeUniString(utf8); + auto uni = strings::MakeUniString(utf8); if (utf8.size() == uni.size()) { // obvious ASCII