U8g2 图形库文字渲染速度优化:同一行扫描线缓存后再写入

一句话:同一行的扫描线先缓存,连续线段合并后再写入屏幕。

U8g2 绘制一个中文字符时,会把字形拆成很多水平线段。旧的写法每得到一段就操作一次 TFT,新的写法先把同一行的连续线段放进 lineBuf,等这一行结束后通过 DMA 一次写入。

U8g2 在这里运行于彩色 TFT 屏幕,像素数据需要携带颜色信息,单次写屏代价更高。这个设备只有 8KB 内存,无法直接放入 LVGL 这类完整 GUI 框架,只能保留 U8g2 的字形解码和自己的显示适配层。

菜单文字数量较多,逐个取模后展开成未压缩点阵会快速消耗 Flash。Flash 空间同样有限,所以字形数据需要保持压缩形式,由 U8g2 在绘制时解码成水平扫描线。后面的优化只处理这些扫描线如何写入 TFT,保留压缩字库和现有文字显示能力。

两种写法的区别

旧路径反复执行:

水平线段 -> 设置 TFT 窗口 -> DMA 写入 -> 等待完成

新路径变成:

水平线段 -> lineBuf -> 设置一次窗口 -> DMA 批量写入

两种算法写出的像素相同,区别是屏幕提交次数。Demo 把中文字符“中”放到两块 32×16 屏幕上,左侧逐段提交,右侧缓存后提交。

同一行扫描线缓存后批量写入

缓存提交的触发点

DisplayAdapter_drawFastHLine() 记录上一段的行号和结束横坐标:

项目中的提交调用是:

DisplayAdapter_drawFastHLine(888, 888, 0, 0xFFFF);

这里的 len0,不会真的绘制像素。888,888 只负责制造一次坐标边界,让缓存中的数据进入 TFT。

适用范围

这项优化只改变水平线段的写屏方式,不改变 U8g2 的 UTF-8 解码和字形查找。中文、英文、数字只要经过 DisplayAdapter_drawFastHLine(),都可以使用同一套缓存逻辑。

当前效果已通过交互 Demo 展示。项目没有记录独立的帧率或耗时数据,因此这里只说明写屏提交次数减少,不给出虚构的加速比例。