- // 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;
+ }