高通字库
版本 V2.0 · 更新于 2026-09-24

7B. GT-MD 流式渲染引擎

GT-MD 是高通自研的 Markdown 流式渲染引擎,位于 lib/gt_latex/gt_md_*,纯 C 实现、无操作系统依赖、以回调方式对接任意 GUI 系统与字库,专为嵌入式设备的 AI 流式输出场景设计。

与 gt_markdown 控件的关系: gt_markdown 控件(7.5 节)基于开源 md4c 组件做嵌入式优化,适合在 GT-HMI Designer2 工程中以零代码方式渲染静态 Markdown 文本;GT-MD 是引擎层 API,直接面向帧缓冲/画布绘制,支持逐块流式处理,适合在自有工程中接大模型流式输出,或对内存占用有严格要求的场景。两者可独立使用。

GT-MD 同时支持 Markdown 语法与内嵌 LaTeX 公式($...$、$$...$$)混合渲染,内嵌公式能力依赖 gt_latex 模块。

GT-MD 排版效果示意(标题层级、有序列表、粗体、行内代码、引用块,内容与本章示例 1 一致)GT-MD 排版效果示意(标题层级、有序列表、粗体、行内代码、引用块,内容与本章示例 1 一致)

编译配置

在 gt_md_config.h 中配置。总开关 GT_MD_ENABLE(默认 1)。各语法特性可独立裁剪,用不到的特性置 0 后不占用 ROM:

宏说明默认值
GT_MD_CFG_ENABLE_HEADING标题 H1~H61
GT_MD_CFG_ENABLE_LIST有序/无序列表(嵌套深度见 GT_MD_CFG_MAX_NEST_DEPTH,默认 8)1
GT_MD_CFG_ENABLE_CODE_BLOCK围栏代码块1
GT_MD_CFG_ENABLE_BLOCKQUOTE引用块1
GT_MD_CFG_ENABLE_HR分隔线 ---1
GT_MD_CFG_ENABLE_BOLD粗体 **text**1
GT_MD_CFG_ENABLE_ITALIC斜体 *text*1
GT_MD_CFG_ENABLE_CODE_SPAN行内代码 `code`1
GT_MD_CFG_ENABLE_STRIKETHROUGH删除线 ~~text~~1
GT_MD_CFG_ENABLE_LATEX内嵌 LaTeX 公式(需 gt_latex)1

常用约束宏:GT_MD_CFG_MAX_NEST_DEPTH(列表最大嵌套深度,默认 8)、GT_MD_CFG_MAX_LINE_LEN(单行最大字节数,默认 256)。

初始化:注册字库与绘制回调

GT-MD 的渲染层不直接访问字库数据,字体与绘制全部通过回调注入,因此可对接高通字库芯片,也可对接用户自有字库:

字库回调(布局阶段按 Unicode 码点查询字形尺寸):

// 字库回调:返回指定字符在指定级别字号下的宽高
static int my_font_get(uint32_t code,
                       const gt_latex_font_level_t *level_cfg,
                       gt_latex_glyph_metrics_t *metrics,
                       void *user_data)
{
    // 从字库查询 code 的字形宽度(高通字库芯片按字库 ID 直接索引)
    metrics->font_w = my_font_get_width(code, level_cfg->size);
    metrics->height = level_cfg->size;   // 字形高度等于字号
    metrics->axis   = level_cfg->size / 2;
    return 0;
}

// 注册字库回调
gt_latex_font_register(my_font_get, NULL);

gt_latex_font_level_t 结构体包含:size(该级字号,像素高度)、font_type(字体类型,用户自定义含义,透传给回调)、font_flags(样式标志,Markdown 扩展字段)。

绘制回调(渲染阶段按码点自取位图绘制,引擎不介入字库数据):

// 注册绘制回调:字形、水平线(引用块/分隔线)、斜线段、圆弧
// 圆弧回调可为 NULL,此时括号等弧线退化为折线绘制
gt_latex_render_register(my_draw_glyph, my_draw_hline,
                         my_draw_line, NULL);

画布结构体 gt_latex_canvas_t:

字段说明
x, y渲染起始坐标
fg_color前景色(字形、线条)
bg_color背景色(可选)
user_data透传给绘制回调的用户数据
ys, ye垂直裁剪区间(绝对坐标,0/0 = 不裁剪),滚动显示时用于只绘制可见区域

API 参考

一体化接口(推荐,静态文本):

函数说明返回值
gt_md_get_size(text, len, &w, &h, max_width)计算渲染尺寸(不绘制)0 成功,负数失败
gt_md_draw(text, len, &canvas, max_width)渲染 Markdown 文本到画布0 成功,负数失败

流式接口(AI 流式输出,峰值内存仅为单块复杂度):

函数说明返回值
gt_md_get_size_stream(text, len, &w, &h, max_width)流式获取渲染尺寸,逐块处理0 成功,负数失败
gt_md_draw_stream(text, len, &canvas, max_width)流式渲染,逐块处理0 成功,负数失败

分步接口(需缓存布局、多次渲染时使用):

函数说明返回值
gt_md_parse_and_layout(text, len, max_width, &parser, &root, &layout)解析 + 布局一步完成0 成功,负数失败
gt_md_render(&layout, &canvas)将布局结果渲染到画布(可多次调用)0 成功,负数失败
gt_md_free_all(&parser, root, &layout)释放 parse_and_layout 分配的所有资源—

逐块迭代器(极低内存模式,块级流式):

函数说明返回值
gt_md_line_iter_init(&it, text, len, max_width)初始化逐块迭代器—
gt_md_line_iter_next_size(&it, &w, &h)获取下一块渲染尺寸GT_MD_OK / GT_MD_EOF / 负数
gt_md_line_iter_next_draw(&it, &canvas)渲染下一块(y 偏移自动累加)GT_MD_OK / GT_MD_EOF / 负数

全局配置:

函数说明
gt_md_set_spacing(spacing) / gt_md_get_spacing(spacing)设置/获取全局间距配置(NULL 恢复默认)
gt_md_set_latex_mode(mode) / gt_md_get_latex_mode()设置/获取内嵌 LaTeX 渲染模式(编译期固定时设置无效)

返回值约定: GT_MD_OK(0) 成功;GT_MD_ERR_PARAM(-1) 参数错误;GT_MD_ERR_NOMEM(-2) 内存不足;GT_MD_ERR_SYNTAX(-3) Markdown 语法错误(通常降级处理);GT_MD_ERR_NO_CB(-6) 未注册必要回调;GT_MD_ERR_EOF(1) 输入结束(仅迭代器使用,非错误)。

示例 1:整段渲染(一体化接口)

// 初始化(系统启动时执行一次)
gt_latex_font_register(my_font_get, NULL);
gt_latex_render_register(my_draw_glyph, my_draw_hline,
                         my_draw_line, NULL);

// 渲染一段 Markdown
const char *text = "## 解题思路\n\n"
                   "1. **先求判别式**:Δ = b² - 4ac\n"
                   "2. 再代入求根公式\n\n"
                   "> 注意判别式的符号\n";

// 先取尺寸,再绘制
uint16_t w, h;
gt_md_get_size(text, strlen(text), &w, &h, 240);   // 限定最大宽度 240px

gt_latex_canvas_t canvas = {
    .x = 0, .y = 0,
    .fg_color = 0x000000,
    .bg_color = 0xFFFFFF,
    .user_data = NULL,
    .ys = 0, .ye = 0,
};
gt_md_draw(text, strlen(text), &canvas, 240);

示例 2:流式渲染(AI 输出逐段上屏)

大模型流式返回场景:每收到一段文本即调用一次流式接口,画布的 y 随已渲染高度累加,实现"边生成边显示":

int16_t cur_y = 0;

// AI 每返回一段文本调用一次
void on_ai_chunk(const char *chunk, uint16_t len)
{
    gt_latex_canvas_t canvas = {
        .x = 0, .y = cur_y,
        .fg_color = 0x000000,
        .user_data = NULL,
        .ys = 0, .ye = 0,
    };
    // 流式绘制:逐块处理,峰值内存仅为单块复杂度
    gt_md_draw_stream(chunk, len, &canvas, 240);

    // 累加本段高度
    uint16_t w, h;
    gt_md_get_size_stream(chunk, len, &w, &h, 240);
    cur_y += h;
}

内存特性

  • 流式接口与逐块迭代器:峰值内存仅为单个 Markdown 块(一个段落/一个列表项等)的解析与布局开销,与全文长度无关,适合 KB 级内存的 MCU。
  • 一体化与分步接口:需持有全文解析结果,适用于静态文本或需要多次渲染同一内容的场景(分步接口布局一次、渲染多次)。