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[] =
{
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.
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;
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 */
{
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 );
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 );
}
}
Vector<CharacterIndex> mIndices;
Vector<float> mAdvance;
+ Vector<float> mOffset;
Vector<CharacterIndex> mCharacterMap;
FontId mFontId;
};
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.
* @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.