Add logs to check glyphs retrieved from HarfBuzz while shaping complex text
[platform/core/uifw/dali-adaptor.git] / text / dali / internal / text-abstraction / shaping-impl.cpp
index 5e33fa5..4d5fd6e 100644 (file)
 #include <harfbuzz/hb-ft.h>
 
 #include <ft2build.h>
+#include <iostream>
+
+namespace
+{
+
+const static uint8_t U2 = 2u;
+const static uint8_t U3 = 3u;
+const static uint8_t U4 = 4u;
+
+uint32_t GetNumberOfUtf8Bytes( const uint32_t* const utf32, uint32_t numberOfCharacters )
+{
+  uint32_t numberOfBytes = 0u;
+
+  const uint32_t* begin = utf32;
+  const uint32_t* end = utf32 + numberOfCharacters;
+
+  for( ; begin < end; ++begin )
+  {
+    const uint32_t code = *begin;
+
+    if( code < 0x80u )
+    {
+      ++numberOfBytes;
+    }
+    else if( code < 0x800u )
+    {
+      numberOfBytes += U2;
+    }
+    else if( code < 0x10000u )
+    {
+      numberOfBytes += U3;
+    }
+    else if( code < 0x200000u )
+    {
+      numberOfBytes += U4;
+    }
+  }
+
+  return numberOfBytes;
+}
+
+uint32_t Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, uint8_t* utf8 )
+{
+  const uint32_t* begin = utf32;
+  const uint32_t* end = utf32 + numberOfCharacters;
+
+  uint8_t* utf8Begin = utf8;
+
+  for( ; begin < end; ++begin )
+  {
+    const uint32_t code = *begin;
+
+    if( code < 0x80u )
+    {
+      *utf8++ = code;
+    }
+    else if( code < 0x800u )
+    {
+      *utf8++ = static_cast<uint8_t>(   code >> 6u )           | 0xc0u; // lead byte for 2 byte sequence
+      *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
+    }
+    else if( code < 0x10000u )
+    {
+      *utf8++ = static_cast<uint8_t>(   code >> 12u )          | 0xe0u; // lead byte for 2 byte sequence
+      *utf8++ = static_cast<uint8_t>( ( code >> 6u )  & 0x3f ) | 0x80u; // continuation byte
+      *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
+    }
+    else if( code < 0x200000u )
+    {
+      *utf8++ = static_cast<uint8_t>(   code >> 18u )          | 0xf0u; // lead byte for 2 byte sequence
+      *utf8++ = static_cast<uint8_t>( ( code >> 12u ) & 0x3f ) | 0x80u; // continuation byte
+      *utf8++ = static_cast<uint8_t>( ( code >> 6u )  & 0x3f ) | 0x80u; // continuation byte
+      *utf8++ = static_cast<uint8_t>(   code          & 0x3f ) | 0x80u; // continuation byte
+    }
+  }
+
+  return utf8 - utf8Begin;
+}
+
+void Utf32ToUtf8( const uint32_t* const utf32, uint32_t numberOfCharacters, std::string& utf8 )
+{
+  utf8.clear();
+
+  uint32_t numberOfBytes = GetNumberOfUtf8Bytes( &utf32[0], numberOfCharacters );
+  utf8.resize( numberOfBytes );
+
+  // This is a bit horrible but std::string returns a (signed) char*
+  Utf32ToUtf8( utf32, numberOfCharacters, reinterpret_cast<uint8_t*>(&utf8[0]) );
+}
+
+}
 
 namespace Dali
 {
@@ -47,6 +138,22 @@ const hb_script_t SCRIPT_TO_HARFBUZZ[] =
 {
   HB_SCRIPT_COMMON,
 
+  HB_SCRIPT_COMMON, // ASCII_DIGITS
+  HB_SCRIPT_COMMON, // ASCII_PS
+
+  HB_SCRIPT_COMMON, // C1_CONTROLS
+  HB_SCRIPT_COMMON, // C1_PS
+  HB_SCRIPT_COMMON, // C1_MATH
+  HB_SCRIPT_COMMON, // SML_P
+  HB_SCRIPT_COMMON, // PHONETIC_U
+  HB_SCRIPT_COMMON, // PHONETIC_SS
+  HB_SCRIPT_COMMON, // NUMERIC_SS
+  HB_SCRIPT_COMMON, // LETTER_LIKE
+  HB_SCRIPT_COMMON, // NUMBER_FORMS
+  HB_SCRIPT_COMMON, // FRACTIONS_NF
+  HB_SCRIPT_COMMON, // NON_LATIN_LED
+  HB_SCRIPT_COMMON, // HWFW_S
+
   HB_SCRIPT_CYRILLIC,
   HB_SCRIPT_GREEK,
   HB_SCRIPT_LATIN,
@@ -61,6 +168,7 @@ const hb_script_t SCRIPT_TO_HARFBUZZ[] =
   HB_SCRIPT_HANGUL,
   HB_SCRIPT_HIRAGANA,
   HB_SCRIPT_KATAKANA,
+  HB_SCRIPT_BOPOMOFO,
 
   HB_SCRIPT_BENGALI,
   HB_SCRIPT_MYANMAR,
@@ -77,8 +185,20 @@ const hb_script_t SCRIPT_TO_HARFBUZZ[] =
   HB_SCRIPT_LAO,
   HB_SCRIPT_THAI,
   HB_SCRIPT_KHMER,
+  HB_SCRIPT_JAVANESE,
+  HB_SCRIPT_SUNDANESE,
+
+  HB_SCRIPT_ETHIOPIC,
+  HB_SCRIPT_OL_CHIKI,
+  HB_SCRIPT_TAGALOG,
+  HB_SCRIPT_MEETEI_MAYEK,
 
   HB_SCRIPT_UNKNOWN, // EMOJI
+  HB_SCRIPT_UNKNOWN, // SYMBOLS1
+  HB_SCRIPT_UNKNOWN, // SYMBOLS2
+  HB_SCRIPT_UNKNOWN, // SYMBOLS3
+  HB_SCRIPT_UNKNOWN, // SYMBOLS4
+  HB_SCRIPT_UNKNOWN, // SYMBOLS5
   HB_SCRIPT_UNKNOWN
 };
 
@@ -165,15 +285,24 @@ struct Shaping::Plugin
     hb_buffer_set_script( harfBuzzBuffer,
                           SCRIPT_TO_HARFBUZZ[ script ] ); /* see hb-unicode.h */
 
-    hb_buffer_set_language( harfBuzzBuffer,
-                            hb_language_from_string( DEFAULT_LANGUAGE,
-                                                     DEFAULT_LANGUAGE_LENGTH ) );
+
+    char* currentLocale = setlocale(LC_MESSAGES,NULL);
+
+    std::istringstream stringStream( currentLocale );
+    std::string localeString;
+    std::getline(stringStream, localeString, '_');
+    hb_buffer_set_language( harfBuzzBuffer, hb_language_from_string( localeString.c_str(), localeString.size() ) );
 
     /* Layout the text */
     hb_buffer_add_utf32( harfBuzzBuffer, text, numberOfCharacters, 0u, numberOfCharacters );
 
     hb_shape( harfBuzzFont, harfBuzzBuffer, NULL, 0u );
 
+    std::string currentText;
+    Utf32ToUtf8( text, numberOfCharacters, currentText );
+
+    DALI_LOG_RELEASE_INFO( "Shape: currentText: %s, font: %s, pointSize: %d\n", currentText.c_str(), fontDescription.path.c_str(), static_cast<int>( fontClient.GetPointSize( fontId ) * FROM_266 ) );
+
     /* Get glyph data */
     unsigned int glyphCount;
     hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( harfBuzzBuffer, &glyphCount );
@@ -232,6 +361,8 @@ struct Shaping::Plugin
         mOffset.PushBack( floor( glyphPositions[i].x_offset * FROM_266 ) );
         mOffset.PushBack( floor( glyphPositions[i].y_offset * FROM_266 ) );
 
+        DALI_LOG_RELEASE_INFO( "glyphIndex: %u, glyph.advance: %f, glyph.xBearing: %f\n", glyphInfo[i].codepoint, floor( glyphPositions[i].x_advance * FROM_266 ), floor( glyphPositions[i].x_offset * FROM_266 ) );
+
         ++i;
       }
     }