
LVGL 的 6.1 版本发布包含了许多令人兴奋的新功能,其中之一就是双向文本支持。
关于这个功能的更多信息可以在文档中找到。
大多数语言使用从左到右(简称 LTR)的书写方向,但某些语言(例如希伯来语)使用从右到左(简称 RTL)的方向。 LVGL 不仅支持 RTL 文本,还支持混合(又称为双向,BiDi)文本渲染。
在 LVGL 上支持混合双向文本需要遵循复杂的 Unicode 双向算法规范,并为资源受限的设备创建自定义实现。
虽然我参与了这项工作,但大部分工作实际上是由 Gabor Kiss-Vamosi 完成的,这非常令人印象深刻,因为他甚至无法阅读任何 RTL 文本!
全球有超过 4 亿人使用 RTL 文本。使用最多的是阿拉伯文。我个人的兴趣是在嵌入式设备上显示希伯来语,所以这是我接下来要讨论的内容,但双向文本支持对阿拉伯文同样有益。
在嵌入式设备上显示希伯来语#
在 LVGL 上显示希伯来语的步骤简单明了:
1. 生成字体#
LVGL 使用自己的字体格式。你可以使用 LVGL 字体转换器将标准的 ttf 字体转换为 LVGL 字体。也有一个在线字体转换器,但我选择使用命令行工具。
字体转换器的安装和使用说明有详细文档,这是我使用的命令行:
node lv_font_conv.js --font FrankRuehlCLM-Medium.ttf -r 0x20-0x7F -r 0x5d0-0x5ea --size 16 --format lvgl --bpp 4 --no-compress -o lv_font_heb_16.cbash作为输入,我提供了一个来自 Culmus 项目的字体,但你也可以使用任何其他 ttf 字体。Unicode 范围 0x20-0x7F 和 0x5d0-0x5ea 仅涵盖最基本的拉丁字符和希伯来字符。
这个命令会生成一个新的 C 文件 lv_font_heb_16.c,它表示字符的字形,可以与 LVGL 一起使用。
2. 构建字体#
字体 C 文件需要与项目的其余部分静态链接,因为不幸的是,目前还无法在运行时加载字体文件。不过,这个功能正在考虑中。
所以要么将它放在 lvgl/src/lv_font/ 下,要么在 Makefile 中指定其位置,这取决于你如何构建 LVGL。
然后编辑 lv_conf.h,将其关联到 LVGL:
#define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(lv_font_heb_16)
#define LV_FONT_DEFAULT &lv_font_heb_16c实际上,你不必设置 LV_FONT_DEFAULT。但如果不设置,你就必须在要显示的每个对象的每个样式上显式设置希伯来语字体(至少在 LVGL v6 中是这样)。
3. 启用双向文本支持#
双向文本支持默认未启用。要启用它,请编辑 lv_conf.h:
#define LV_USE_BIDI 1c4. 显示希伯来语!#
LVGL 支持 UTF-8,所以你只需为任何标签或文本框设置 UTF-8 文本即可。
设置基础方向#
显示 RTL 文本时,包含文本的对象的基础方向性很重要。
基础方向会影响标签内文本的对齐方式、混合 RTL 和 LTR 文本一起显示的方式,甚至影响对象本身的显示和对齐方式。
例如,具有 LTR 基础方向的表格的第一列是最左边的列,而 RTL 表格的第一列是最右边的列。
如果整个页面或屏幕应该是 RTL 的,只需在 lv_conf.h 中设置 LV_BIDI_BASE_DIR_DEF,或者在运行时设置屏幕(或页面)的基础方向就足够了。
它看起来怎么样?#
一个非常简单的 C 语言示例:
/*创建一个使用包含希伯来字符的字体的样式*/
LV_FONT_DECLARE(lv_font_heb_16);
static lv_style_t style;
lv_style_copy(&style, &lv_style_plain);
style.text.font = &lv_font_heb_16;
/*创建一个标签并设置其文本*/
lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
lv_label_set_style(label, LV_LABEL_STYLE_MAIN, &style);
lv_label_set_text(label, "שלום LittlevGL");
lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);c
以下是一些使用 MicroPython 的更多示例,但同样的事情也可以用 C 语言实现。
我没有在 lv_conf.h 中更改基础方向,而是为我的屏幕设置它。在该屏幕上创建的所有其他对象的基础方向也将设置为 RTL。
scr = lv.obj()
scr.set_base_dir(lv.BIDI_DIR.RTL)python创建 3 个选项卡:
tabview = lv.tabview(scr)
tab1 = tabview.add_tab("1. אחד")
tab2 = tabview.add_tab("2. שתיים")
tab3 = tabview.add_tab("3. שלוש")python创建一个表格:
style_cell1 = lv.style_t()
lv.style_copy(style_cell1, lv.style_plain)
style_cell1.body.border.width = 1
style_cell1.body.border.color = lv.color_hex3(0xFFF)
style_cell2 = lv.style_t()
lv.style_copy(style_cell2, lv.style_plain)
style_cell2.body.border.width = 1
style_cell2.body.border.color = lv.color_hex3(0xFFF)
style_cell2.body.main_color = lv.color_hex3(0xAAA)
style_cell2.body.grad_color = lv.color_hex3(0xAAA)
table = lv.table(tab1)
table.set_style(table.STYLE.CELL1, style_cell1);
table.set_style(table.STYLE.CELL2, style_cell2);
table.set_style(table.STYLE.BG, lv.style_transp_tight);
table.set_col_cnt(2);
table.set_row_cnt(4);
table.set_cell_align(0, 0, lv.label.ALIGN.CENTER);
table.set_cell_align(0, 1, lv.label.ALIGN.CENTER);
table.set_cell_type(0, 0, 2);
table.set_cell_type(0, 1, 2);
table.set_cell_value(0, 0, "שם");
table.set_cell_value(1, 0, "תפוח");
table.set_cell_value(2, 0, "בנננה");
table.set_cell_value(3, 0, "לימון");
table.set_cell_value(0, 1, "מחיר");
table.set_cell_value(1, 1, "$7");
table.set_cell_value(2, 1, "$4");
table.set_cell_value(3, 1, "$6");python效果如下:

你可以看到选项卡和表格列都是从右到左排序的,因为它们从 scr 继承了 RTL 方向性。
这是另一个混合 RTL 和 LTR 文本的示例:

你可以在此链接上使用 LVGL 在线模拟器查看此示例、运行它甚至修改它。
阿拉伯语呢?#
阿拉伯文也是一种 RTL 文本,但我们发现它比希伯来语更复杂。为了让 LVGL 支持阿拉伯语,它需要一些目前仍缺少的额外功能:
- 连字
- 变音符号
- 上下文相关的文本塑形(每个字符可以有多种形状)
如果你愿意帮助在 LVGL 中实现这些缺失的功能,请在论坛上与我们联系!
