Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
714 changes: 714 additions & 0 deletions src/fw/applib/graphics/bidi.c

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions src/fw/applib/graphics/bidi.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* SPDX-FileCopyrightText: 2026 Ahmed Hussein */
/* SPDX-FileCopyrightText: 2026 Khalid Nuaim (kaluaim) */
/* SPDX-License-Identifier: Apache-2.0 */

#pragma once

#include "utf8.h"

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

//! Minimal bidirectional text engine, a subset of Unicode UAX 9.
//!
//! Implements the rules that matter for a single line of watch text:
//! P2/P3 (paragraph direction), W1 (marks follow their base), W2 and W4-W7
//! (numbers take their class from the letter before them and absorb their
//! separators and terminators), N1/N2 (neutrals take the surrounding direction,
//! otherwise the paragraph direction), I1/I2 (embedding levels 0-2) and L4
//! (mirrored glyphs). The caller reorders runs by level (L2). Bracket pairs
//! (N0), explicit directional controls, isolates and levels above two are not
//! implemented.

//! Check whether a UTF-8 range needs bidirectional processing at all.
//! Scans raw bytes over every block the class table calls strong right-to-left,
//! so pure-ASCII text costs one comparison per byte and stays on the LTR path.
//! @param start Pointer to start of UTF-8 string
//! @param end Pointer to end of UTF-8 string (exclusive)
//! @return true if the range contains at least one right-to-left character
bool bidi_is_needed(const utf8_t *start, const utf8_t *end);

//! Resolve the paragraph direction of a UTF-8 range (UAX 9 P2/P3).
//! The first strong character wins; ranges without one are left-to-right.
//! @param start Pointer to start of UTF-8 string
//! @param end Pointer to end of UTF-8 string (exclusive)
//! @return true if the paragraph reads right-to-left
bool bidi_paragraph_is_rtl(const utf8_t *start, const utf8_t *end);

//! Find the extent of the directional run starting at @p pos.
//!
//! Weak types are folded into the neighbouring number and neutrals are
//! resolved against the surrounding runs, so the returned range is a maximal
//! stretch at one embedding level. Levels follow UAX 9 I1/I2 and stay within
//! 0-2: even levels read left-to-right, odd levels right-to-left.
//!
//! @param line_start Start of the line, used to look behind @p pos
//! @param pos Position to start the run at, must be within the line
//! @param end End of the line (exclusive)
//! @param para_is_rtl Paragraph direction, from \ref bidi_paragraph_is_rtl
//! @param[out] run_level Embedding level of the returned run
//! @return Pointer to the first codepoint after the run, or @p pos on failure
utf8_t *bidi_next_run(const utf8_t *line_start, utf8_t *pos, const utf8_t *end, bool para_is_rtl,
uint8_t *run_level);

//! Return the mirrored form of a codepoint (UAX 9 L4).
//! Glyphs such as brackets are drawn mirrored inside a right-to-left run.
//! Codepoints without a mirrored form are returned unchanged.
Codepoint bidi_mirror_codepoint(Codepoint cp);

//! Reverse the codepoints of a run for right-to-left display.
//! Combining marks stay behind the base character they attach to.
//! @param src Source UTF-8 string
//! @param src_len Length of source string in bytes
//! @param dest Destination buffer for the reversed string
//! @param dest_size Size of destination buffer in bytes
//! @return Number of bytes written to dest (excluding null terminator), or 0 on failure
size_t bidi_reverse_run(const utf8_t *src, size_t src_len, utf8_t *dest, size_t dest_size);

//! Check if a UTF-8 string range contains any shapeable Arabic letters.
//! @param start Pointer to start of UTF-8 string
//! @param end Pointer to end of UTF-8 string (exclusive)
//! @return true if the range contains at least one shapeable Arabic letter
bool bidi_contains_arabic(const utf8_t *start, const utf8_t *end);
208 changes: 0 additions & 208 deletions src/fw/applib/graphics/rtl_support.c

This file was deleted.

42 changes: 0 additions & 42 deletions src/fw/applib/graphics/rtl_support.h

This file was deleted.

Loading