Commit dda08dd
applib/graphics: add a minimal BiDi engine
RTL rendering reverses the codepoints of each right-to-left run but never
mirrors the glyphs that call for it, so a bracket keeps facing the same
way after the reversal and "(مرحبا)" draws as ")مرحبا(". Neutral
characters are attached to whichever run happens to be open rather than
resolved against their neighbours, so the brackets around an embedded
Latin word can land in different runs and be treated inconsistently. A
combining mark is reversed away from the letter it attaches to.
Replace rtl_support.c with bidi.c, a subset of Unicode UAX 9 sized for a
single line of watch text: P2/P3 for the paragraph direction, W1 so a
mark takes the class of the character it follows, W4-W7 so a number keeps
the separators and terminators that belong to it, N1/N2 for neutrals,
I1/I2 and L2 so runs carry an embedding level and reorder by it, and L4
for mirrored glyphs. Arabic letters are AL, so a European number after
one becomes an Arabic number (W2) and terminators and signs no longer bind
to it, matching what the phone renders. Bracket pairs (N0), explicit
directional controls, isolates and embedding levels above two are out of
scope; N0 and a linear neutral resolver are tracked as a follow-up.
The weak-LTR digit and numeric separator behaviour already in
rtl_support.c is preserved, but moves from a special case inside the
reversal into the run classification: European and Arabic-Indic numbers
resolve to their own left-to-right run, which is the level UAX 9 assigns
them in either paragraph direction. Resolving neutrals also removes the
need to peel trailing spaces into their own segment, so
rtl_segment_content_end() goes away with it.
bidi_is_needed() gates the whole path on a raw byte scan covering every
block the classifier calls strong right-to-left, so the gate and the class
table agree and nothing is right-aligned while still being drawn in
logical order. Text with none of those bytes costs one comparison per byte
and keeps taking the existing left-to-right path, unchanged.
Runs carry an embedding level rather than a direction bit, because a
number following a right-to-left run sits one level deeper than the text
around it: without the level, "Total <arabic> 123" cannot be told apart
from ordinary Latin and L2 leaves the digits on the wrong side of the
Arabic. Paragraph direction is resolved from the start of the paragraph
rather than the start of the visual line, so a wrapped paragraph does not
change base direction part way down.
The run splitter in text_layout.c collapses into one bidi_next_run() call
and mirroring is applied in both the width pass and the draw pass so the
two agree. Lam-alef ligature shaping and the segment cap are untouched.
test_rtl_support.c is replaced by test_bidi.c, which keeps its digit and
separator coverage expressed as run boundaries rather than as reversal
output.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Khalid Nuaim <i@kalua.im>1 parent bb02ebe commit dda08dd
18 files changed
Lines changed: 1445 additions & 577 deletions
File tree
- src/fw/applib/graphics
- tests/fw
- apps
- system_apps
- health
- launcher
- music
- timeline
- weather
- workout
- watch/kickstart
- graphics
- services/timeline
- ui
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
This file was deleted.
This file was deleted.
0 commit comments