bevy
bevy copied to clipboard
Simple bidi integration
This is an alternative solution to https://github.com/bevyengine/bevy/pull/4672
Objective
- short: unicode bidi support for text and text2d
- When text is presented in horizontal lines, most scripts display characters from left to right. However, there are several scripts (such as Arabic or Hebrew) where the natural ordering of horizontal text in display is from right to left. If all of the text has a uniform horizontal direction, then the ordering of the display text is unambiguous. However, because these right-to-left scripts use digits that are written from left to right, the text is actually bidirectional: a mixture of right-to-left and left-to-right text. In addition to digits, embedded words from English and other scripts are also written from left to right, also producing bidirectional text. Without a clear specification, ambiguities can arise in determining the ordering of the displayed characters when the horizontal direction of the text is not uniform. This is solved by the Unicode Bidirectional Algorithm.
Solution
- using the unicode-bidi crate and allowing for bidi correction in the Text component
Hmm. I'm having a bit of trouble piecing together how this might look in practice. Could you put together a simple bidirectional_text.rs
example?
It should be completely transparent to the user - for example the text example: I just changed the String to some characters with RTL:
and the result is a rendered text with corrected directions (well - if the font would support those characters ... ):
Standard examples with RTL/Bidi text and new font containing hebrew chars.
I would like to avoid the risk of having sections
not be in sync with bidi_corrected
. Would it make sense to remove pub
from sections
(and adding accessors), and update directly bidi_corrected
when updating sections
?
This makes working with sections less convenient and might trigger the bidi correction way too often (every time a text or style is changed - even if it is changed several times in one update). I'm actually not sure if moving the bidi correction into the Text is the best way - to me it seems more in line with the ECS to move the corrected sections into an additional component and have the text_system react to text changes with creating the bidi sections once per update (as in the first approach). Maybe we can make that less visible (and therefore confusing) for the user?
this PR seems nearly ready and hope it get merged it the next release
This makes working with sections less convenient and might trigger the bidi correction way too often (every time a text or style is changed - even if it is changed several times in one update). I'm actually not sure if moving the bidi correction into the Text is the best way - to me it seems more in line with the ECS to move the corrected sections into an additional component and have the text_system react to text changes with creating the bidi sections once per update (as in the first approach). Maybe we can make that less visible (and therefore confusing) for the user?
What about adding a boolean flag to indicate whether the bidi correction is up-to-date? Would add some more complexity, but then we could check the flag if it's up-to-date, if yes we just use the cached value, if no we recompute the correction. When the text is edited or newly created we set the flag to false. That way we could minimize the number of corrections applied and only apply them when the text is actually rendered
This makes working with sections less convenient and might trigger the bidi correction way too often (every time a text or style is changed - even if it is changed several times in one update). I'm actually not sure if moving the bidi correction into the Text is the best way - to me it seems more in line with the ECS to move the corrected sections into an additional component and have the text_system react to text changes with creating the bidi sections once per update (as in the first approach). Maybe we can make that less visible (and therefore confusing) for the user?
What about adding a boolean flag to indicate whether the bidi correction is up-to-date? Would add some more complexity, but then we could check the flag if it's up-to-date, if yes we just use the cached value, if no we recompute the correction. When the text is edited or newly created we set the flag to false. That way we could minimize the number of corrections applied and only apply them when the text is actually rendered
On a second thought, it would be better to make the cached value an Option
instead of introducing a boolean flag, then we can simply set it to None
when the text changes and ensure that the previously cached value is not used in that case
@TimJentzsch Thank you for your input - maybe you could have a look at the alternative implementation https://github.com/bevyengine/bevy/pull/4672 ? I would really like some feedback :)
Overall good quality on the code, I realize I need to read up on the details of bidi in general to feel able to review this properly. While this looks straightforward in its implementation, I think I prefer #4672 to this one.
I do like the .
add_section()
builder pattern. Maybe we should add it as a separate PR?
Reading up on Bidi is certainly interesting, but luckily all the heavy lifting is done in the dependency ;-) Adding the builder pattern in the other PR would be easy - or we just add it as a separate PR afterwards.
or we just add it as a separate PR afterwards.
This would be my preference. We're already in the process of improving the UX around similar issues, see this converastion on discord