Shaping fixes: 40/38240/2
authorVictor Cebollada <v.cebollada@samsung.com>
Tue, 14 Apr 2015 10:33:31 +0000 (11:33 +0100)
committerVictor Cebollada <v.cebollada@samsung.com>
Wed, 15 Apr 2015 12:49:00 +0000 (13:49 +0100)
  - Offset metric added to place some glyphs correctly.
  - Fix wrong reordering for some right to left strings.

Change-Id: I3663e040eeaa015a523c8e1e04b6aeb0ed523b5b
Signed-off-by: Victor Cebollada <v.cebollada@samsung.com>
text/dali/internal/text-abstraction/font-client-impl.cpp
text/dali/internal/text-abstraction/font-client-impl.h
text/dali/internal/text-abstraction/font-client-plugin-impl.cpp
text/dali/internal/text-abstraction/shaping-impl.cpp
text/dali/public-api/text-abstraction/font-client.cpp
text/dali/public-api/text-abstraction/font-client.h

index b749fe9..0b4b6e7 100644 (file)
@@ -80,6 +80,12 @@ void FontClient::SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi  )
   }
 }
 
+void FontClient::GetDpi( unsigned int& horizontalDpi, unsigned int& verticalDpi )
+{
+  horizontalDpi = mDpiHorizontal;
+  verticalDpi = mDpiVertical;
+}
+
 void FontClient::SetDefaultFontFamily( const std::string& fontFamilyName,
                                        const std::string& fontStyle )
 {
index d3c963c..c465ead 100644 (file)
@@ -61,6 +61,11 @@ public:
   void SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi );
 
   /**
+   * @copydoc Dali::FontClient::GetDpi()
+   */
+  void GetDpi( unsigned int& horizontalDpi, unsigned int& verticalDpi );
+
+  /**
    * @copydoc Dali::FontClient::SetDefaultFontFamily()
    */
   void SetDefaultFontFamily( const std::string& fontFamilyName,
index 1947c7f..6e5198c 100644 (file)
@@ -519,15 +519,13 @@ bool FontClient::Plugin::GetGlyphMetrics( GlyphInfo* array,
           array[i].height = static_cast< float >( ftFace->glyph->metrics.height ) * FROM_266 ;
           if( horizontal )
           {
-            array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
-            array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
-            array[i].advance  = static_cast< float >( ftFace->glyph->metrics.horiAdvance ) * FROM_266;
+            array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingX ) * FROM_266;
+            array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.horiBearingY ) * FROM_266;
           }
           else
           {
-            array[i].xBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
-            array[i].yBearing = static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
-            array[i].advance  = static_cast< float >( ftFace->glyph->metrics.vertAdvance ) * FROM_266;
+            array[i].xBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingX ) * FROM_266;
+            array[i].yBearing += static_cast< float >( ftFace->glyph->metrics.vertBearingY ) * FROM_266;
           }
         }
         else
index 32591e0..b0702df 100644 (file)
@@ -39,10 +39,9 @@ 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[] =
 {
@@ -101,8 +100,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 +125,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;
@@ -147,17 +162,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 = rtlDirection ? ( 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 +233,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 +245,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 +257,7 @@ struct Shaping::Plugin
 
   Vector<CharacterIndex> mIndices;
   Vector<float>          mAdvance;
+  Vector<float>          mOffset;
   Vector<CharacterIndex> mCharacterMap;
   FontId                 mFontId;
 };
index 3375dd0..80a202f 100644 (file)
@@ -58,6 +58,11 @@ void FontClient::SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi  )
   GetImplementation(*this).SetDpi( horizontalDpi, verticalDpi );
 }
 
+void FontClient::GetDpi( unsigned int& horizontalDpi, unsigned int& verticalDpi )
+{
+  GetImplementation(*this).GetDpi( horizontalDpi, verticalDpi );
+}
+
 void FontClient::SetDefaultFontFamily( const std::string& fontFamilyName,
                                        const std::string& fontStyle )
 {
index 4bfb44e..5215d18 100644 (file)
@@ -113,6 +113,15 @@ public:
   void SetDpi( unsigned int horizontalDpi, unsigned int verticalDpi );
 
   /**
+   * @brief Retrieves the DPI previously set to the target window.
+   *
+   * @note Multiple windows are not currently supported.
+   * @param[out] horizontalDpi The horizontal resolution in DPI.
+   * @param[out] verticalDpi The vertical resolution in DPI.
+   */
+  void GetDpi( unsigned int& horizontalDpi, unsigned int& verticalDpi );
+
+  /**
    * Set the default font family and its style that should be used by the font client.
    *
    * @param[in] fontFamilyName The default name of the font's family.
@@ -251,7 +260,8 @@ public:
    * @brief Retrieve the metrics for a series of glyphs.
    *
    * @param[in,out] array An array of glyph-info structures with initialized FontId & GlyphIndex values.
-   * On return, the remaining metrics values will be initialized e.g. glyph size & bearing values.
+   * It may contain the advance and an offset set into the bearing from the shaping tool.
+   * On return, the glyph's size value will be initialized. The bearing value will be updated by adding the font's glyph bearing to the one set by the shaping tool.
    * @param[in] size The size of the array.
    * @param[in] horizontal True for horizontal layouts (set to false for vertical layouting).
    * @return True if all of the requested metrics were found.