nagisa-render
把一段类 Markdown 的标记文本,或一份 Rust 构建器拼出的文档,排版渲染成图片字节(PNG / WebP)。纯 CPU 管线:cosmic-text 整形(断行 / 字体回退 / CJK + 拉丁 + emoji 混排)+ tiny-skia 光栅,不依赖浏览器、GPU 或系统字体,内置中文字体开箱出图。是 nagisa 框架的排版引擎,也可单独使用。
全功能样张,由 examples/gallery.rs 渲出
安装
bot 场景经 nagisa 门面(挂在 render feature 后面):
= { = "0.5", = ["render"] }
use *;
单独使用:cargo add nagisa-render。
两种写法
标记文本(类 Markdown,适合「一大段文字」):
use ;
let png = render_markup?;
Rust 构建器(类型安全,适合从数据生成卡片):
use ;
let doc = new
.heading
.paragraph
.table
.build;
let png = render_document?;
两种写法产出同一个 Document;parse_markup 拿到 Document 后还能往 blocks 里接着拼构建器块(上面的样张就是这么混出来的)。构建器闭包写花括号块(|p| { p.text(..); }),单表达式链式返回 &mut 会撞闭包生命周期。
能排什么
- 块级:标题(1–6 级)、段落、有序 / 无序列表(可嵌套、起始序号可设)、任务列表(
✓/□)、引用(可嵌套)、行内与块级代码(语言标签渲在盒角)、分割线、表格、多栏并排(按权重分宽)、面板(底色 / 边框 / 圆角 / 内边距 / 投影的卡片容器,作并排栏整栏时自动拉齐行高)、块级图、进度条。 - 行内:粗 / 细 / 任意字重(100–900 真字形)、斜体、下划线、删除线、文字色、高亮 / 自定底色、字号倍率、字族切换(黑 / 宋 / 楷 / 等宽 / 具名)、链接(取文字按强调色渲染)、圈注与着重点(整段或逐字,可定径定色)、边注(挂行外,不挤布局)、文字阴影、硬换行、反斜杠转义。
- 表格:自适应列宽、按列限宽、铺满可用宽(
expand)、各列对齐、按列 / 行 / 格设文字样式与背景色、紧凑度(pad_x/pad_y)与网格线(外框 / 横 / 竖)可调、表头浅底开关。 - 图片:PNG / JPEG / WebP / GIF 解码,缩放(像素 / 百分比)、对齐、富文本图注,外加装饰层——圆角裁切、边框、投影、角标、水印(画在图面上,不改布局)。
标记语法速查
Markdown 基底加少量扩展。解析宽容:认不出的写法退化成普通文字。
| 写法 | 效果 |
|---|---|
# …–###### … |
标题 1–6 级;块尾 {align=center} 设对齐 |
**粗** *斜* ***粗斜*** ~~删~~ `码` ==高亮== |
行内基础样式,可嵌套 |
[文字](URL) |
链接(取文字按强调色渲染,URL 不展示) |
[文字]{属性} |
属性 span,见下表 |
- / 9. / - [x] |
无序 / 有序(起始序号取首项)/ 任务列表,缩进嵌套 |
> |
引用,>> 嵌套 |
```lang |
代码块 |
--- |
分割线(*** / ___ 同,3 个起步) |
| GFM 表格 | 分隔行 |:--|:-:|--:| 定列对齐 |
 /  |
块级图;@名字 从 RenderOptions::images 取字节 |
::: center … ::: |
对齐围栏(left / right / center / justify),可嵌套 |
::: columns 内嵌 ::: col 权重 |
多栏围栏;::: col 权重 {bg=…} = 卡片栏(自动等高) |
::: panel {bg=… border=… rounded=… pad=… shadow} |
面板(卡片);属性全缺省即主题默认卡片样 |
行尾 \ |
硬换行 |
属性 span 的键(逗号或空白分隔):
| 属性 | 含义 |
|---|---|
color=#hex / bg=#hex |
文字色 / 底色 |
bold / light / weight=500 |
字重 |
italic / underline / strike |
斜 / 下划 / 删除 |
size=1.2 |
字号倍率 |
font=sans|serif|kai|mono|字族名 |
字族 |
ring / ring=#hex / ring-radius / ring-rx / ring-ry / ring-stroke / ring-each |
圈注:自适应或定径,整段一圈或逐字 |
dot / dot=#hex / dot-radius / dot-each |
着重点:整段一点或正字法逐字 |
aside / aside=left |
边注:挂行外,不参与布局 |
输出与配置
都在 RenderOptions(默认:逻辑宽 960、亮色主题、scale 2、PNG):
- 格式:
.png()(默认,通用)/.png_fast()(约 8 倍快、体积大 ~40%)/.webp()(无损,文字图体积最小且快;单边 > 16383px 报错)/.webp_or_png()(WebP 优先,超限自动落 PNG)。文字图建议 WebP。 - 清晰度:
.fast()(1×)/.standard()(1.5×)/.sharp()(2×,默认)/.ultra()(3×),或.with_scale(f)。所有尺寸都是逻辑值,输出 = 逻辑尺寸 × scale。 - 主题
Theme:亮 / 暗预设(Theme::light()/Theme::dark())+ 全部配色 / 字族名 / 字号 / 行高 / 标题阶梯可改。 - 页眉 / 页脚
PageChrome:与文档无关的固定标识(品牌 / 署名 / 出处),配在选项上所有出图统一带;富文本、左右分栏(trailing)、页脚满幅色带(band)皆可。 - 具名图
images:标记文本里@名字的字节来源。
入口四个:
| 函数 | 产出 |
|---|---|
render_markup |
标记文本 → 图片字节 |
render_document |
Document → 图片字节 |
render_to_rgba |
Document → RGBA 图,供进一步合成 |
measure_document |
只排版不绘制,返回物理像素尺寸——按高度上限切多图时先量再渲 |
字体
内置兜底 Noto Sans SC + JetBrains Mono 正斜(zstd 压缩内嵌,首次渲染时解压),保证开箱出中文、粗细是真字形。衬线 / 楷体两个角色不随包内置(crates.io 包体上限),字族名默认指 Noto Serif SC 与 LXGW WenKai GB,自备对应字体即生效,缺则回退黑体:
let fonts = builder
.bundled // 内置兜底(默认开)
.data // 自备数据,裸字节或 zstd 压缩皆可
.dir // 字体目录
.system // 系统字体
.build?;
let opts = default.with_fonts;
FontHandle 构建一次很贵,Arc 共享,建好复用。CJK 没有斜体字面,italic 由仿斜(错切)合成;等宽拉丁有真斜体,优先命中。
emoji 表现序列(含 VS16 升级、肤色修饰、ZWJ 合字、键帽、旗帜)统一切到彩色 emoji 字族(Theme::font_emoji,默认 Noto Color Emoji)——黑体自带的单色 emoji 字面不会抢跑;该字体不内置,系统装有即用,缺则回退单色。
样张
examples/gallery.rs 按特性渲样张到 out/*.png:
# 衬线 / 楷体样张要真字形的话,指一个放字体的目录:
GALLERY_FONTS=path/to/fonts
License
MIT OR Apache-2.0