- 开发工具
- 文档
【免费下载链接】plantuml
Generate diagrams from textual description
PlantUML 在传统的 PNG/SVG 等图形输出之外,提供了一种面向触觉阅读场景的braille-png输出格式:它把时序图、类图等 UML 图先转换成一张由“凸点”构成的 Braille 点阵网格,再以 PNG 图片形式输出,从而可以被盲文打印/触觉显示设备读取。本文以 src/main/java/net/sourceforge/plantuml/braille/readme.md 为骨架,结合braille包的完整源码,从命令行入口、格式注册、栅格化渲染管线、字符映射、尺寸计算到支持范围逐一展开,帮助你理解并复用这一无障碍输出能力。
一、包定位:braille包在 PlantUML 中的角色
braille包的官方定位非常明确——该包提供"用于将图导出为 Braille 输出格式的类"(export diagram to a Braille output format),其包级注释也确认了这一职责(见 package-info.java)。整个包共 14 个源文件,可以按职责划分为四层:
| 层次 | 类 | 职责 |
|---|---|---|
| 入口/画布 | UGraphicBraille.java | 实现 Klimt 绘图接口的 Braille 后端,注册各形状的驱动 |
| 栅格模型 | BrailleGrid.java、Coords.java | 点阵状态存储、坐标换算、线/矩形/曲线/多边形光栅化 |
| 字符映射 | BrailleChar.java、BrailleCharFactory.java、BrailleUtils.java | 字母/数字/符号到 Braille 六点(6-dot)位图的映射 |
| 形状驱动 | DriverLineBraille.java、DriverRectangleBraille.java、DriverPolygonBraille.java、DriverDotPathBraille.java、DriverTextBraille.java、DriverCenteredCharacterBraille.java | 把 Klimt 几何/文本对象写入栅格 |
| 输出 | BrailleDrawer.java | 把栅格渲染成最终 PNG |
该包最早源于论坛上的需求讨论(QA-4752,主题为把类图翻译成盲文),是 PlantUML 无障碍(accessibility)方向的一个探索性实现。需要说明的是,这是一个实验性、面向特定触觉场景的功能:它输出的仍然是 PNG 图片(点阵图的"像素化"呈现),并且目前只覆盖了部分图形对象(见后文"支持范围")。
二、从命令行激活:--braille标志与格式注册
Braille 输出通过标准命令行参数激活。在 CliFlag.java 中定义了:
T_BRAILLE("--braille", Arity.UNARY_BOOLEAN, FileFormat.BRAILLE_PNG),对应的文件格式枚举在 FileFormat.java 中注册为:
BRAILLE_PNG("braille-png", "image/png"), //典型用法:
# 将 diagram.puml 渲染为 braille-png 输出(生成 diagram.braille.png) plantuml -tbraille diagram.puml # 或使用长选项 plantuml --braille diagram.puml关于文件名的两个细节(见 FileFormat.java):
- 输出文件后缀为
.braille.png(而不是普通的.png),便于与常规 PNG 输出区分; - 该格式的 MIME 类型声明为
image/png,即它本质上仍是一张 PNG 位图。
在 PlantUmlTask.java 中可以看到,Ant 构建任务同样支持format="braille"并映射到FileFormat.BRAILLE_PNG,因此--braille能力在 CLI 与 Ant 集成中均可使用。由于BrailleUtils.isBraille(char)判定Character.UnicodeBlock.BRAILLE_PATTERNS(见 BrailleUtils.java),说明该格式与 Unicode 盲文字符块(U+2800 起的 Braille Patterns)直接相关,栅格最终呈现的就是这些盲文图案的点位。
三、渲染管线:从 Klimt 绘图指令到 Braille 栅格
PlantUML 所有输出格式共享同一套 Klimt 绘图模型(UGraphic+UDriver机制)。Braille 输出也不例外,其管线如下:
- 选择 StringBounder:
FileFormat.getDefaultStringBounder()在BRAILLE_PNG分支返回 StringBounderBraille.java(见 FileFormat.java),所有文字度量按 Braille 字符规格计算(详见第五节)。 - 创建 UGraphic:
TextBlockExporter在BRAILLE_PNG分支实例化new UGraphicBraille(backcolor, colorMapper, stringBounder)(见 TextBlockExporter.java)。 - 注册驱动:
UGraphicBraille.register()为每种 Klimt 形状注册对应的UDriver,并显式忽略部分形状(见 UGraphicBraille.java):
private void register() { ignoreShape(URectangle.class); registerDriver(URectangle.class, new DriverRectangleBraille(this)); registerDriver(UText.class, new DriverTextBraille()); registerDriver(ULine.class, new DriverLineBraille(this)); registerDriver(UPolygon.class, new DriverPolygonBraille(this)); ignoreShape(UEllipse.class); ignoreShape(UImage.class); ignoreShape(UPath.class); registerDriver(DotPath.class, new DriverDotPathBraille()); registerDriver(UCenteredCharacter.class, new DriverCenteredCharacterBraille()); }- 栅格累积:各个
Driver*Braille把几何对象解析成离散点,写入同一个 BrailleGrid 栅格。 - 导出 PNG:
UGraphicBraille.writeToStream()借助TextBlockExporter.builder(new BrailleDrawer(grid), new FileFormatOption(FileFormat.PNG), false)把栅格绘制成 PNG 输出(见 UGraphicBraille.java)——即"Braille 栅格 → PNG 位图"的最终一步由BrailleDrawer完成。
其中UGraphicBraille继承自 Klimt 的AbstractUGraphic<BrailleGrid>并实现ClipContainer,这意味着裁剪(clip)能力同样作用于 Braille 渲染,DriverRectangleBraille与DriverLineBraille中都会先取clipContainer.getClip()对几何做裁剪后再写入栅格(见 DriverRectangleBraille.java、DriverLineBraille.java)。
四、栅格模型:BrailleGrid与Coords
BrailleGrid是 Braille 输出的核心数据结构(见 BrailleGrid.java),要点如下:
- 分辨率单位
quanta:由UGraphicBraille.QUANTA = 4定义(见 UGraphicBraille.java)。所有浮点坐标经toInt(value) = (int) Math.round(value / quanta)换算成整数栅格坐标,quanta即一个盲文点位的尺寸。 - 状态存储:用
Set<Coords> on保存所有被激活的点位;Coords是(x, y)整数坐标的不可变值对象,equals/hashCode由x + y * 8192决定(见 Coords.java)。当点位写入时,minX/minY/maxX/maxY边界会同步更新,供BrailleDrawer计算画布尺寸。 - 几何光栅化:
rectangle(x, y, w, h):四条边分别调用hline/vline,逐点激活;line(x1,y1,x2,y2):仅支持水平或垂直线(斜线会打印warning line到 stderr 并忽略),见 BrailleGrid.java;drawDotPath(x, y, DotPath):把贝塞尔曲线逐段细分(subdivide),当控制点间距大于quanta时持续递归二分,直到逼近到点级精度(BrailleGrid.java);drawPolygon(points):逐边递归中点细分(a.distance(b) > quanta时取中点一分为二),并闭合首尾(BrailleGrid.java)。
这种"递归细分直到小于一个 quanta"的策略,是 Braille 栅格能表达曲线/斜边的关键:虽然直线line只支持横竖,但多边形与曲线路径通过细分逼近出近似形状。
五、文字渲染:Braille 六点字符映射
这是整个包最"Blind-friendly"的部分:图中文字不再渲染为普通字体,而是逐个字符翻译成盲文点位。
5.1 字符 → 六点位图映射
BrailleChar.java 用一个 0~63 的整数id表示一个 Braille 字符的六点组合。draw()把 6 个点映射到 2 列 × 3 行的栅格单元上(见 BrailleChar.java):
| 栅格偏移 | 位权重 |
|---|---|
| (x+0, y+0) | 1 |
| (x+0, y+1) | 2 |
| (x+0, y+2) | 4 |
| (x+1, y+0) | 8 |
| (x+1, y+1) | 16 |
| (x+1, y+2) | 32 |
fromChar(char)是完整的映射表,覆盖:
- 26 个小写/大写字母(a–z / A–Z),例如
a→1、b→1+2、c→1+8、w→2+8+16+32 等标准 Grade 1 Braille 字母编码; - 数字 0–9:复用 a–j 的字母位型(
1→a、2→b …0→j),符合盲文中数字前缀 + a–j 的惯例; - 常用标点:空格→0、
'→2、;→2+4、:→2+16、!→2+4+16、(/)→2+4+16+32、?/./"→2+4+32、,→4、-→4+32; - 未支持字符的兜底:返回
63(全 6 点),即"未定义字符"会以六点全亮的方式在触觉上提示读者(BrailleChar.java)。
5.2 文本驱动与工厂
- BrailleCharFactory.build(String) 把字符串逐字符转成
List<BrailleChar>(不可变列表); - DriverTextBraille 负责排布:每个字符绘制后横向推进
quanta * 3(即 3 个点位宽度,对应 2 列点 + 1 列间距),起点整体做y -= quanta*3; x += quanta的偏移校正; - DriverCenteredCharacterBraille 处理
UCenteredCharacter(如带圈字符)的居中场景。
5.3 文字度量:StringBounderBraille
布局引擎需要知道文字占多大空间,StringBounderBraille.calculateDimension()给出与渲染一致的公式(见 StringBounderBraille.java):
final int nb = BrailleCharFactory.build(text).size(); final double quanta = UGraphicBraille.QUANTA; // = 4 final double height = 5 * quanta; // 3 行点 + 上下边距 final double width = 3 * nb * quanta + 1; // 每字符 3 个点位宽getDescent()返回一个quanta,getFileFormat()声明FileFormat.BRAILLE_PNG。这样,布局阶段与渲染阶段对"一个 Braille 字符"的认知完全一致,避免文字溢出或重叠。
六、最终输出:BrailleDrawer如何把栅格画成 PNG
BrailleDrawer.java 实现TextBlock,承担"栅格 → 图形"的最终绘制:
- 常量:
step = 9(网格间距)、spotSize = 5(凸点直径); - 尺寸:
calculateDimension()依据栅格边界计算width = (maxX-minX)*step + spotSize + 2、height = (maxY-minY)*step + spotSize + 2; - 绘制顺序:
- 以
#F0F0F0浅灰绘制横竖参考网格线(辅助触觉定位); - 切回黑色,遍历栅格中所有激活点位,在每个
(x,y)处用UEllipse.build(spotSize, spotSize)画一个实心圆作为凸点(BrailleDrawer.java)。
- 以
输出结果就是一张"浅灰网格 + 黑色凸点"的 PNG 位图,盲文打印设备/软件可依据凸点分布将其转译为可触摸的盲文图形。
七、支持范围与已知限制(基于源码的客观评估)
从UGraphicBraille.register()的注册表可以客观推断当前支持与不支持的图形对象:
支持:
- 矩形(
URectangle)——仅轮廓边框,无填充(DriverRectangleBraille中与颜色/渐变相关的 SVG 代码均被注释掉,见 DriverRectangleBraille.java); - 水平/垂直线(
ULine); - 多边形(
UPolygon)与贝塞尔路径(DotPath)——通过递归细分逼近; - 文本(
UText)与居中字符(UCenteredCharacter)——按盲文字符位图渲染; - 裁剪(clip)语义。
不支持(ignoreShape,直接跳过):椭圆(UEllipse)、图片(UImage)、通用路径(UPath)。其中椭圆被忽略意味着:圆形节点、圆角矩形、泳道圆角等依赖椭圆的图形元素不会出现在 Braille 输出中;BrailleGrid.line()对斜线会打印warning line并跳过,因此箭头等斜线段也无法直接表达。这些限制说明该功能更适合表达以矩形框和横竖连线为主的简单结构图(如基础类图骨架、时序图消息线),读者在选用时应结合实际图型验证。
另外两点工程细节值得注意:
UGraphicBraille构造器中有一段被注释掉的"渐变背景"(HtmlColorGradient)相关代码(UGraphicBraille.java),佐证了当前版本不渲染颜色/渐变信息,只保留几何轮廓;DriverDotPathBraille在param.getColor().isTransparent() == false时才绘制(DriverDotPathBraille.java),即透明色路径会被跳过。
八、源码地图:继续深入阅读的入口
如果你希望进一步研究或扩展 Braille 输出,推荐按以下路径阅读:
- 格式定义与命令行:
src/main/java/net/sourceforge/plantuml/FileFormat.java(BRAILLE_PNG分支、后缀规则)、src/main/java/net/sourceforge/plantuml/cli/CliFlag.java(--braille标志) - 绘图后端:
src/main/java/net/sourceforge/plantuml/braille/UGraphicBraille.java - 栅格与几何光栅化:
src/main/java/net/sourceforge/plantuml/braille/BrailleGrid.java、src/main/java/net/sourceforge/plantuml/braille/Coords.java - 字符映射:
src/main/java/net/sourceforge/plantuml/braille/BrailleChar.java、src/main/java/net/sourceforge/plantuml/braille/BrailleCharFactory.java - 文字度量:
src/main/java/net/sourceforge/plantuml/StringBounderBraille.java - 形状驱动:
src/main/java/net/sourceforge/plantuml/braille/Driver*.java(共 6 个) - 最终 PNG 绘制:
src/main/java/net/sourceforge/plantuml/braille/BrailleDrawer.java - 官方文档入口:
src/main/java/net/sourceforge/plantuml/braille/readme.md(本文所依据的目录说明文档)
九、小结
PlantUML 的 Braille 输出是一条完整独立的渲染管线:命令行--braille/-tbraille→FileFormat.BRAILLE_PNG→StringBounderBraille(盲文文字度量)→UGraphicBraille(Klimt 后端,注册 6 类驱动)→BrailleGrid(以quanta=4为分辨率的点阵 + 递归细分光栅化)→BrailleDrawer(网格+凸点 PNG)。它把 UML 图翻译成触觉可读的盲文点阵,是 PlantUML 面向无障碍场景的一个实验性功能;其文字部分采用 Grade 1 盲文字母/数字/标点映射,图形部分以矩形、横竖线与细分曲线为主,椭圆、图片、斜线等暂不支持。理解这层"文本 → 点位 → PNG"的转换机制,无论是用于无障碍方案集成、还是在此基础上扩展新的 Braille 图形支持,都能做到有的放矢。
- 开发工具
- 文档
【免费下载链接】plantuml
Generate diagrams from textual description
相关推荐
Linux Braille Console(盲文控制台):在内核早期引导阶段输出到 VisioBraille 设备
Linux Braille Console(盲文控制台):在内核早期引导阶段输出到 VisioBraille 设备 导读 本文讲解 Linux 内核中的"盲文控
操作系统内核驱动驱动开发虚拟化嵌入式网络存储CPython 输入与输出(Input and Output)完整指南:从格式化输出到文件读写与 JSON 持久化
CPython 输入与输出(Input and Output)完整指南:从格式化输出到文件读写与 JSON 持久化 导读 程序输出(Output)与输入(Inp
编程语言语言运行时解释器标准库PlantUML GraphML 导出深入解析:从文本描述到标准图交换格式
PlantUML GraphML 导出深入解析:从文本描述到标准图交换格式 GraphML 是一种基于 XML 的通用图数据交换格式,可被众多图分析工具(如 y
开发工具文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考