From a4cc2afc677af711f82256a6e318ee816857c7e5 Mon Sep 17 00:00:00 2001 From: Victor Cebollada Date: Tue, 14 Apr 2015 11:33:31 +0100 Subject: [PATCH] Shaping fixes: - 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 --- .../internal/text-abstraction/font-client-impl.cpp | 6 ++ .../internal/text-abstraction/font-client-impl.h | 5 ++ .../text-abstraction/font-client-plugin-impl.cpp | 10 +-- .../internal/text-abstraction/shaping-impl.cpp | 94 ++++++++++++++++++---- .../public-api/text-abstraction/font-client.cpp | 5 ++ .../dali/public-api/text-abstraction/font-client.h | 12 ++- 6 files changed, 111 insertions(+), 21 deletions(-) diff --git a/text/dali/internal/text-abstraction/font-client-impl.cpp b/text/dali/internal/text-abstraction/font-client-impl.cpp index b749fe9..0b4b6e7 100644 --- a/text/dali/internal/text-abstraction/font-client-impl.cpp +++ b/text/dali/internal/text-abstraction/font-client-impl.cpp @@ -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 ) { diff --git a/text/dali/internal/text-abstraction/font-client-impl.h b/text/dali/internal/text-abstraction/font-client-impl.h index d3c963c..c465ead 100644 --- a/text/dali/internal/text-abstraction/font-client-impl.h +++ b/text/dali/internal/text-abstraction/font-client-impl.h @@ -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, diff --git a/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp b/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp index 1947c7f..6e5198c 100644 --- a/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp +++ b/text/dali/internal/text-abstraction/font-client-plugin-impl.cpp @@ -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 diff --git a/text/dali/internal/text-abstraction/shaping-impl.cpp b/text/dali/internal/text-abstraction/shaping-impl.cpp index 32591e0..b0702df 100644 --- a/text/dali/internal/text-abstraction/shaping-impl.cpp +++ b/text/dali/internal/text-abstraction/shaping-impl.cpp @@ -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( 1.3f * static_cast( 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::ConstIterator indicesIt = mIndices.Begin(); Vector::ConstIterator advanceIt = mAdvance.Begin(); + Vector::ConstIterator offsetIt = mOffset.Begin(); Vector::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 mIndices; Vector mAdvance; + Vector mOffset; Vector mCharacterMap; FontId mFontId; }; diff --git a/text/dali/public-api/text-abstraction/font-client.cpp b/text/dali/public-api/text-abstraction/font-client.cpp index 3375dd0..80a202f 100644 --- a/text/dali/public-api/text-abstraction/font-client.cpp +++ b/text/dali/public-api/text-abstraction/font-client.cpp @@ -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 ) { diff --git a/text/dali/public-api/text-abstraction/font-client.h b/text/dali/public-api/text-abstraction/font-client.h index 4bfb44e..5215d18 100644 --- a/text/dali/public-api/text-abstraction/font-client.h +++ b/text/dali/public-api/text-abstraction/font-client.h @@ -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. -- 2.7.4