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);这里的 len 是 0,不会真的绘制像素。888,888 只负责制造一次坐标边界,让缓存中的数据进入 TFT。
适用范围
这项优化只改变水平线段的写屏方式,不改变 U8g2 的 UTF-8 解码和字形查找。中文、英文、数字只要经过 DisplayAdapter_drawFastHLine(),都可以使用同一套缓存逻辑。
当前效果已通过交互 Demo 展示。项目没有记录独立的帧率或耗时数据,因此这里只说明写屏提交次数减少,不给出虚构的加速比例。