"""Illustrate UAX9 L2 with supplied levels, not a bidi implementation; PNG to cwd.""" from pathlib import Path import matplotlib matplotlib.use("Agg") import matplotlib.pyplot as plt from matplotlib.patches import FancyBboxPatch def reverse_at_level(items, threshold): result = list(items) start = 0 while start < len(result): if result[start][1] < threshold: start += 1 continue end = start + 1 while end < len(result) and result[end][1] >= threshold: end += 1 result[start:end] = reversed(result[start:end]) start = end return result def main(): logical = [("a", 0), ("R1", 1), ("R2", 1), ("1", 2), ("2", 2), ("R3", 1), ("b", 0)] after_two = reverse_at_level(logical, 2) visual = reverse_at_level(after_two, 1) assert [x[0] for x in visual] == ["a", "R3", "1", "2", "R2", "R1", "b"] assert [x[0] for x in after_two] == ["a", "R1", "R2", "2", "1", "R3", "b"] colors = {0: ("#e8f1eb", "#236541"), 1: ("#e5eef8", "#245d91"), 2: ("#fcf0da", "#8c5b0c")} fig = plt.figure(figsize=(9, 4.8), dpi=100, facecolor="white") ax = fig.add_axes([0.025, 0.18, 0.95, 0.64]) ax.set_xlim(0, 10.2) ax.set_ylim(-0.1, 3) ax.axis("off") for y, label, items in [(2.25, "Logical order", logical), (1.25, "Reverse level 2", after_two), (0.25, "Then levels 1–2", visual)]: ax.text(0.05, y + 0.28, label, fontsize=11, va="center", color="#243641") for j, (token, level) in enumerate(items): x = 2.45 + j * 1.06 background, foreground = colors[level] ax.add_patch(FancyBboxPatch((x, y), 0.87, 0.6, boxstyle="round,pad=0.035", facecolor=background, edgecolor=foreground, linewidth=1.1)) ax.text(x + 0.435, y + 0.36, token, ha="center", va="center", fontsize=13, weight="bold", color=foreground) ax.text(x + 0.435, y + 0.105, f"level {level}", ha="center", va="center", fontsize=8, color=foreground) fig.suptitle("Nested reversals preserve the order of the digits", y=0.96, fontsize=15, weight="bold", color="#172330") fig.text(0.5, 0.86, "UAX #9, rule L2: each pass reverses contiguous items at or above its level", ha="center", fontsize=10.5, color="#45535d") fig.text(0.5, 0.085, "R1, R2 and R3 stand for separate right-to-left characters; read every row left to right.", ha="center", fontsize=10, color="#45535d") fig.text(0.5, 0.035, "Illustrative supplied levels. Resolving levels, shaping and mirroring are separate steps.", ha="center", fontsize=9.5, color="#45535d") fig.savefig(Path.cwd() / (Path(__file__).stem + ".png"), dpi=100, facecolor="white", transparent=False) plt.close(fig) if __name__ == "__main__": main()