[3.0] Javanese and Sundanese scripts added.
[platform/core/uifw/dali-adaptor.git] / text / dali / internal / text-abstraction / shaping-impl.cpp
index 516eb68..3df10a2 100644 (file)
@@ -20,8 +20,8 @@
 
 // INTERNAL INCLUDES
 #include <singleton-service-impl.h>
-#include <dali/public-api/text-abstraction/font-client.h>
-#include <dali/public-api/text-abstraction/glyph-info.h>
+#include <dali/devel-api/text-abstraction/font-client.h>
+#include <dali/devel-api/text-abstraction/glyph-info.h>
 #include <dali/integration-api/debug.h>
 
 // EXTERNAL INCLUDES
@@ -39,31 +39,70 @@ namespace TextAbstraction
 namespace Internal
 {
 
-const unsigned int HIGH_QUALITY_PIXEL_SIZE = 200u;  // Pixel size sent to FreeType2 FT_Set_Char_Size() for high quality glyphs.
 const char*        DEFAULT_LANGUAGE = "en";
 const unsigned int DEFAULT_LANGUAGE_LENGTH = 2u;
-const float        TO_PIXELS = 64.f;
+const float        FROM_266 = 1.0f / 64.0f;
 
 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,
+
   HB_SCRIPT_ARABIC,
-  HB_SCRIPT_DEVANAGARI,
+  HB_SCRIPT_HEBREW,
+
+  HB_SCRIPT_ARMENIAN,
+  HB_SCRIPT_GEORGIAN,
+
+  HB_SCRIPT_HAN,
+  HB_SCRIPT_HANGUL,
+  HB_SCRIPT_HIRAGANA,
+  HB_SCRIPT_KATAKANA,
+  HB_SCRIPT_BOPOMOFO,
+
   HB_SCRIPT_BENGALI,
-  HB_SCRIPT_GURMUKHI,
+  HB_SCRIPT_MYANMAR,
+  HB_SCRIPT_DEVANAGARI,
   HB_SCRIPT_GUJARATI,
-  HB_SCRIPT_ORIYA,
-  HB_SCRIPT_TAMIL,
-  HB_SCRIPT_TELUGU,
+  HB_SCRIPT_GURMUKHI,
   HB_SCRIPT_KANNADA,
   HB_SCRIPT_MALAYALAM,
+  HB_SCRIPT_ORIYA,
   HB_SCRIPT_SINHALA,
-  HB_SCRIPT_HAN,
-  HB_SCRIPT_HANGUL,
-  HB_SCRIPT_KHMER,
+  HB_SCRIPT_TAMIL,
+  HB_SCRIPT_TELUGU,
+
   HB_SCRIPT_LAO,
   HB_SCRIPT_THAI,
-  HB_SCRIPT_MYANMAR,
+  HB_SCRIPT_KHMER,
+  HB_SCRIPT_JAVANESE,
+  HB_SCRIPT_SUNDANESE,
+
+  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
 };
 
@@ -101,8 +140,16 @@ struct Shaping::Plugin
     mIndices.Clear();
     mAdvance.Clear();
     mCharacterMap.Clear();
+    mOffset.Clear();
     mFontId = fontId;
 
+    // Reserve some space to avoid reallocations.
+    const Length numberOfGlyphs = static_cast<Length>( 1.3f * static_cast<float>( numberOfCharacters ) );
+    mIndices.Reserve( numberOfGlyphs );
+    mAdvance.Reserve( numberOfGlyphs );
+    mCharacterMap.Reserve( numberOfGlyphs );
+    mOffset.Reserve( 2u * numberOfGlyphs );
+
     TextAbstraction::FontClient fontClient = TextAbstraction::FontClient::Get();
 
     // Get the font's path file name from the font Id.
@@ -118,7 +165,15 @@ struct Shaping::Plugin
       return 0u;
     }
 
-    FT_Set_Pixel_Sizes( face, HIGH_QUALITY_PIXEL_SIZE, HIGH_QUALITY_PIXEL_SIZE );
+    unsigned int horizontalDpi = 0u;
+    unsigned int verticalDpi = 0u;
+    fontClient.GetDpi( horizontalDpi, verticalDpi );
+
+    FT_Set_Char_Size( face,
+                      0u,
+                      fontClient.GetPointSize( fontId ),
+                      horizontalDpi,
+                      verticalDpi );
 
     /* Get our harfbuzz font struct */
     hb_font_t* harfBuzzFont;
@@ -127,9 +182,9 @@ struct Shaping::Plugin
     /* Create a buffer for harfbuzz to use */
     hb_buffer_t* harfBuzzBuffer = hb_buffer_create();
 
-    const bool rtlDiection = ( ARABIC == script );
+    const bool rtlDirection = IsRightToLeftScript( script );
     hb_buffer_set_direction( harfBuzzBuffer,
-                             rtlDiection ? HB_DIRECTION_RTL : HB_DIRECTION_LTR ); /* or LTR */
+                             rtlDirection ? HB_DIRECTION_RTL : HB_DIRECTION_LTR ); /* or LTR */
 
     hb_buffer_set_script( harfBuzzBuffer,
                           SCRIPT_TO_HARFBUZZ[ script ] ); /* see hb-unicode.h */
@@ -147,17 +202,62 @@ struct Shaping::Plugin
     unsigned int glyphCount;
     hb_glyph_info_t* glyphInfo = hb_buffer_get_glyph_infos( harfBuzzBuffer, &glyphCount );
     hb_glyph_position_t *glyphPositions = hb_buffer_get_glyph_positions( harfBuzzBuffer, &glyphCount );
-
-    const Length lastGlyphIndex = glyphCount - 1u;
-    for( Length i = 0u; i < glyphCount; ++i )
+    const GlyphIndex lastGlyphIndex = glyphCount - 1u;
+    for( GlyphIndex i = 0u; i < glyphCount; )
     {
-      // If the direction is right to left, Harfbuzz retrieves the glyphs in the visual order.
-      // The glyphs are needed in the logical order to layout the text in lines.
-      const Length index = rtlDiection ? ( lastGlyphIndex - i ) : i;
-
-      mIndices.PushBack( glyphInfo[index].codepoint );
-      mAdvance.PushBack( glyphPositions[index].x_advance / TO_PIXELS );
-      mCharacterMap.PushBack( glyphInfo[index].cluster );
+      if( rtlDirection )
+      {
+        // If the direction is right to left, Harfbuzz retrieves the glyphs in the visual order.
+        // The glyphs are needed in the logical order to layout the text in lines.
+        // Do not change the order of the glyphs if they belong to the same cluster.
+        GlyphIndex rtlIndex = lastGlyphIndex - i;
+
+        unsigned int cluster = glyphInfo[rtlIndex].cluster;
+        unsigned int previousCluster = cluster;
+        Length numberOfGlyphsInCluster = 0u;
+
+        while( ( cluster == previousCluster ) )
+        {
+          ++numberOfGlyphsInCluster;
+          previousCluster = cluster;
+
+          if( rtlIndex > 0u )
+          {
+            --rtlIndex;
+
+            cluster = glyphInfo[rtlIndex].cluster;
+          }
+          else
+          {
+            break;
+          }
+        }
+
+        rtlIndex = lastGlyphIndex - ( i + ( numberOfGlyphsInCluster - 1u ) );
+
+        for( GlyphIndex j = 0u; j < numberOfGlyphsInCluster; ++j )
+        {
+          const GlyphIndex index = rtlIndex + j;
+
+          mIndices.PushBack( glyphInfo[index].codepoint );
+          mAdvance.PushBack( floor( glyphPositions[index].x_advance * FROM_266 ) );
+          mCharacterMap.PushBack( glyphInfo[index].cluster );
+          mOffset.PushBack( floor( glyphPositions[index].x_offset * FROM_266 ) );
+          mOffset.PushBack( floor( glyphPositions[index].y_offset * FROM_266 ) );
+        }
+
+        i += numberOfGlyphsInCluster;
+      }
+      else
+      {
+        mIndices.PushBack( glyphInfo[i].codepoint );
+        mAdvance.PushBack( floor( glyphPositions[i].x_advance * FROM_266 ) );
+        mCharacterMap.PushBack( glyphInfo[i].cluster );
+        mOffset.PushBack( floor( glyphPositions[i].x_offset * FROM_266 ) );
+        mOffset.PushBack( floor( glyphPositions[i].y_offset * FROM_266 ) );
+
+        ++i;
+      }
     }
 
     /* Cleanup */
@@ -173,9 +273,10 @@ struct Shaping::Plugin
   {
     Vector<CharacterIndex>::ConstIterator indicesIt = mIndices.Begin();
     Vector<float>::ConstIterator advanceIt = mAdvance.Begin();
+    Vector<float>::ConstIterator offsetIt = mOffset.Begin();
     Vector<CharacterIndex>::ConstIterator characterMapIt = mCharacterMap.Begin();
 
-    for( Length index = 0u, size = mIndices.Count(); index < size; ++index )
+    for( GlyphIndex index = 0u, size = mIndices.Count(); index < size; ++index )
     {
       GlyphInfo& glyph = *( glyphInfo + index );
       CharacterIndex& glyphToCharacter = *( glyphToCharacterMap + index );
@@ -184,6 +285,10 @@ struct Shaping::Plugin
       glyph.index = *( indicesIt + index );
       glyph.advance = *( advanceIt + index );
 
+      const GlyphIndex offsetIndex = 2u * index;
+      glyph.xBearing = *( offsetIt + offsetIndex );
+      glyph.yBearing = *( offsetIt + offsetIndex + 1u );
+
       glyphToCharacter = *( characterMapIt + index );
     }
   }
@@ -192,6 +297,7 @@ struct Shaping::Plugin
 
   Vector<CharacterIndex> mIndices;
   Vector<float>          mAdvance;
+  Vector<float>          mOffset;
   Vector<CharacterIndex> mCharacterMap;
   FontId                 mFontId;
 };