return false;
}
-
-BidiDirection GetBidiCharacterDirection(FriBidiCharType characterDirection)
-{
- switch(characterDirection)
- {
- case FRIBIDI_TYPE_LTR: // Left-To-Right letter.
- {
- return LEFT_TO_RIGHT;
- }
- case FRIBIDI_TYPE_AL: // Arabic Letter.
- case FRIBIDI_TYPE_RTL: // Right-To-Left letter.
- {
- return RIGHT_TO_LEFT;
- }
- case FRIBIDI_TYPE_AN: // Arabic Numeral.
- case FRIBIDI_TYPE_ES: // European number Separator.
- case FRIBIDI_TYPE_ET: // European number Terminator.
- case FRIBIDI_TYPE_EN: // European Numeral.
- default:
- {
- return NEUTRAL;
- }
- }
-}
} // namespace
struct BidirectionalSupport::Plugin
*/
struct BidirectionalInfo
{
- FriBidiCharType* characterTypes; ///< The type of each character (right, left, neutral, ...)
- FriBidiLevel* embeddedLevels; ///< Embedded levels.
- FriBidiParType paragraphDirection; ///< The paragraph's direction.
+ FriBidiCharType* characterTypes; ///< The type of each character (right, left, neutral, ...)
+ FriBidiBracketType* bracketTypes; ///< Input list of bracket types as returned by fribidi_get_bracket_types().
+ FriBidiLevel* embeddedLevels; ///< Embedded levels.
+ FriBidiParType paragraphDirection; ///< The paragraph's direction.
};
Plugin()
free(info->embeddedLevels);
free(info->characterTypes);
+ free(info->bracketTypes);
delete info;
}
}
// Retrieve the paragraph's direction.
bidirectionalInfo->paragraphDirection = matchLayoutDirection == true ? (layoutDirection == LayoutDirection::RIGHT_TO_LEFT ? FRIBIDI_PAR_RTL : FRIBIDI_PAR_LTR) : (fribidi_get_par_direction(bidirectionalInfo->characterTypes, numberOfCharacters));
+ bidirectionalInfo->bracketTypes = reinterpret_cast<FriBidiBracketType*>(malloc(numberOfCharacters * sizeof(FriBidiBracketType)));
+ if(!bidirectionalInfo->bracketTypes)
+ {
+ free(bidirectionalInfo->bracketTypes);
+ delete bidirectionalInfo;
+ return 0;
+ }
+
+ fribidi_get_bracket_types(paragraph, numberOfCharacters, bidirectionalInfo->characterTypes, bidirectionalInfo->bracketTypes);
+
// Retrieve the embedding levels.
- if(fribidi_get_par_embedding_levels(bidirectionalInfo->characterTypes, numberOfCharacters, &bidirectionalInfo->paragraphDirection, bidirectionalInfo->embeddedLevels) == 0)
+ if(fribidi_get_par_embedding_levels_ex(bidirectionalInfo->characterTypes, bidirectionalInfo->bracketTypes, numberOfCharacters, &bidirectionalInfo->paragraphDirection, bidirectionalInfo->embeddedLevels) == 0)
{
free(bidirectionalInfo->characterTypes);
+ free(bidirectionalInfo->bracketTypes);
delete bidirectionalInfo;
return 0;
}
// Free resources and destroy the container.
free(bidirectionalInfo->embeddedLevels);
free(bidirectionalInfo->characterTypes);
+ free(bidirectionalInfo->bracketTypes);
delete bidirectionalInfo;
*it = NULL;
{
const BidirectionalInfo* const bidirectionalInfo = *(mParagraphBidirectionalInfo.Begin() + bidiInfoIndex);
- const CharacterDirection paragraphDirection = GetBidiParagraphDirection(bidirectionalInfo->paragraphDirection);
- CharacterDirection previousDirection = paragraphDirection;
-
for(CharacterIndex index = 0u; index < numberOfCharacters; ++index)
{
CharacterDirection& characterDirection = *(directions + index);
- CharacterDirection nextDirection = false;
-
- characterDirection = false;
-
- // Get the bidi direction.
- const BidiDirection bidiDirection = GetBidiCharacterDirection(*(bidirectionalInfo->characterTypes + index));
-
- if(RIGHT_TO_LEFT == bidiDirection)
- {
- characterDirection = true;
- nextDirection = true;
- }
- else if(NEUTRAL == bidiDirection)
- {
- // For neutral characters it check's the next and previous directions.
- // If they are equals set that direction. If they are not, sets the paragraph's direction.
- // If there is no next, sets the paragraph's direction.
- nextDirection = paragraphDirection;
-
- // Look for the next non-neutral character.
- Length nextIndex = index + 1u;
- for(; nextIndex < numberOfCharacters; ++nextIndex)
- {
- BidiDirection nextBidiDirection = GetBidiCharacterDirection(*(bidirectionalInfo->characterTypes + nextIndex));
- if(nextBidiDirection != NEUTRAL)
- {
- nextDirection = RIGHT_TO_LEFT == nextBidiDirection;
- break;
- }
- }
-
- // Calculate the direction for all the neutral characters.
- characterDirection = previousDirection == nextDirection ? previousDirection : paragraphDirection;
-
- // Set the direction to all the neutral characters.
- // The indices from currentIndex + 1u to nextIndex - 1u are neutral characters.
- ++index;
-
- for(; index < nextIndex; ++index)
- {
- CharacterDirection& nextCharacterDirection = *(directions + index);
- nextCharacterDirection = characterDirection;
- }
-
- // Set the direction of the next non-neutral character.
- if(nextIndex < numberOfCharacters)
- {
- *(directions + nextIndex) = nextDirection;
- }
- }
- previousDirection = nextDirection;
+ // Checks if the character is rtl oriented.
+ // I.e even a neutral character can become rtl if surrounded by rtl characters.
+ characterDirection = FRIBIDI_IS_RTL(*(bidirectionalInfo->embeddedLevels + index));
+
+ // NOTE
+ // We are discontinuing the previous character direction determination logic.
+ // The previous logic was too heuristic and had many shortcomings in handling various RTL cases.
+ // The key change in this update is that character direction is determined based on embedding levels,
+ // including bracket information.
+ // The character direction determined here will affect the behavior of the GetMirroredText() function.
+ // BTW, Harfbuzz(hb_shape) also supports text mirroring.
+ // To use this, we need to pass the character direction at the embedding level to hb_buffer_set_direction,
+ // which is currently challenging for us.
+ // If this is implemented, we will no longer need to perform GetMirroredText().
}
}