Kitty终端中的文本尺寸调整协议详解
协议概述
在传统终端中,由于终端是基于等宽字符网格的,通常只支持单一文本尺寸。Kitty终端引入的文本尺寸调整协议打破了这一限制,允许在终端中显示不同大小的文本,既支持比基础文本更大的尺寸,也支持更小的尺寸。
这个协议解决了终端生态中长期存在的一个关键问题:如何准确确定字符应占用的单元格宽度。通过这个协议,应用程序可以在屏幕上交错显示不同尺寸的文本,实现标题、上标等排版效果。
快速入门
使用这个协议非常简单,通过发送特定的控制序列即可实现不同尺寸的文本显示:
# 显示双倍大小文本
printf "\e]_text_size_code;s=2;双倍大小文本\a\n\n"
# 显示三倍大小文本
printf "\e]_text_size_code;s=3;三倍大小文本\a\n\n\n"
# 显示半高文本
printf "\e]_text_size_code;n=1:d=2;半高文本\a\n"
对于半宽文本,可以进一步指定宽度:
printf "\e]_text_size_code;n=1:d=2:w=1;半\a\e]66;n=1:d=2:w=1;宽\a\n"
控制序列详解
协议使用一个OSC控制序列:
ESC ] _text_size_code ; 元数据 ; 文本 BEL/ST
其中元数据是键值对列表,支持以下参数:
| 键 | 值范围 | 默认值 | 描述 | |----|--------|--------|------| | s | 1-7 | 1 | 整体缩放比例,文本将在s*w×s的单元格块中渲染 | | w | 0-7 | 0 | 文本应占用的宽度单元格数 | | n | 0-15 | 0 | 分数缩放的分子 | | d | 0-15 | 0 | 分数缩放的分母 | | v | 0-2 | 0 | 垂直对齐方式(0-顶部,1-底部,2-居中) | | h | 0-2 | 0 | 水平对齐方式(0-左,1-右,2-居中) |
工作原理
协议通过允许客户端程序告诉终端在多单元格中渲染文本来工作。终端可以根据指定的空间调整实际使用的字体大小。
关键参数是s(比例)和w(宽度)。当w=0时,终端像平常一样将文本分割到单元格中,但每个单元格现在是s×s的块。例如,文本"abc"和s=2会被分割为:
│a░│b░│c░│
│░░│░░│░░│
当w非零时,它指定文本应占用的宽度单元格数。所有文本必须在s*w单元格中渲染。
分数缩放
除了整数比例外,协议还支持分数缩放,通过n(分子)和d(分母)参数实现。分数缩放不影响文本占用的单元格数,只调整单元格内渲染的字体大小。
分数缩放可以实现:
- 正常大小文本但上下各留半行空白(s=2:n=1:d=2:v=2)
- 上标(n=1:d=2)
- 下标(n=1:d=2:v=1)
解决终端字符宽度问题
终端生态中长期存在一个问题:客户端程序和终端对字符串应占用的单元格数可能不一致。这个协议通过让客户端程序负责确定字符串宽度并明确告诉终端来解决这个问题。
客户端可以进行它认为合适的字素分割,然后使用适当的w值将分割后的字符串发送给终端,确保终端按照客户端的预期渲染文本。
检测协议支持
要检测终端是否支持此协议,可以使用CPR(光标位置报告)控制序列:
- 发送CR+CPR
- 发送文本尺寸调整序列(w=2)
- 发送CPR
- 发送文本尺寸调整序列(s=2)
- 发送CPR
通过比较三次CPR响应的光标位置,可以确定终端支持哪些功能。
与其他终端控制的交互
协议不改变终端的字符网格本质,大多数终端控制仍假设一个字符一个单元格。以下是主要交互规则:
- 光标移动:按单单元格增量移动,可以定位到多字符内的任何单元格
- 编辑控制:
- 插入/删除字符:会分割并擦除受影响的多字符
- 擦除操作:会擦除受影响区域内的多字符
- 插入/删除行:会擦除受影响的多行字符
实现建议
对于终端开发者,实现时需要注意:
- 多字符的渲染和擦除规则
- 与现有终端控制的兼容性
- 光标在多字符内的显示方式
- 编辑操作对多字符的影响
对于应用程序开发者,建议:
- 合理使用w参数确保文本正确显示
- 对非ASCII字符明确指定宽度
- 避免在单个序列中发送过长文本
- 实现适当的协议检测机制
这个协议为终端带来了更丰富的文本显示能力,同时保持了与传统终端应用的兼容性,是终端技术发展的重要一步。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考