1
0

feat: 实现字体主题系统和东亚字体支持

实现完整的字体主题系统,支持可复用字体配置、预设类别和扩展属性。
同时修复中文字体渲染问题,确保 Source Han Sans 等东亚字体正确显示。

核心功能:
- 字体主题配置:metadata.fonts 和 fonts_default
- 三种引用方式:整体引用、继承覆盖、独立定义
- 预设字体类别:sans、serif、mono、cjk-sans、cjk-serif
- 扩展字体属性:family、underline、strikethrough、line_spacing、
  space_before、space_after、baseline、caps
- 表格字体字段:font 和 header_font 替代旧的 style.font_size
- 引用循环检测和属性继承链
- 模板字体继承支持

东亚字体修复:
- 添加 _set_font_with_eastasian() 方法
- 同时设置拉丁字体、东亚字体和复杂脚本字体
- 修复中文字符使用默认字体的问题

测试:
- 58 个单元测试覆盖所有字体系统功能
- 3 个集成测试验证端到端场景
- 移除旧语法相关测试

文档:
- 更新 README.md 添加字体主题系统使用说明
- 更新 README_DEV.md 添加技术文档
- 创建 4 个示例 YAML 文件
- 同步 delta specs 到主 specs

归档:
- 归档 font-theme-system 变更到 openspec/changes/archive/

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 10:38:59 +08:00
parent 7ef29ea039
commit bd12fce14b
22 changed files with 3142 additions and 103 deletions

View File

@@ -0,0 +1,207 @@
# Font Extended
## Purpose
扩展字体属性在现有 size、bold、italic、color、align 基础上,新增 family、underline、strikethrough、line_spacing、space_before、space_after、baseline、caps 等属性,提供更完整的字体样式控制能力。
## Requirements
### Requirement: 元素 font 必须支持 family 属性
font 字段 SHALL 支持 family 属性,用于指定字体族名称。
#### Scenario: 设置字体族
- **WHEN** 元素定义 font: {family: "Arial"}
- **THEN** 系统将字体族设置为 Arial
#### Scenario: family 字段为 None
- **WHEN** 元素定义 font: {size: 18}(未定义 family
- **THEN** 系统使用继承或默认的字体族
### Requirement: 元素 font 必须支持 underline 属性
font 字段 SHALL 支持 underline 属性,控制文本是否带下划线。
#### Scenario: 启用下划线
- **WHEN** 元素定义 font: {underline: true}
- **THEN** 系统为文本添加下划线
#### Scenario: 禁用下划线
- **WHEN** 元素定义 font: {underline: false}
- **THEN** 系统不为文本添加下划线
#### Scenario: underline 未定义
- **WHEN** 元素定义 font: {size: 18}(未定义 underline
- **THEN** 系统使用继承或默认的下划线设置
### Requirement: 元素 font 必须支持 strikethrough 属性
font 字段 SHALL 支持 strikethrough 属性,控制文本是否带删除线。
#### Scenario: 启用删除线
- **WHEN** 元素定义 font: {strikethrough: true}
- **THEN** 系统为文本添加删除线
#### Scenario: 禁用删除线
- **WHEN** 元素定义 font: {strikethrough: false}
- **THEN** 系统不为文本添加删除线
#### Scenario: strikethrough 未定义
- **WHEN** 元素定义 font: {size: 18}(未定义 strikethrough
- **THEN** 系统使用继承或默认的删除线设置
### Requirement: 元素 font 必须支持 line_spacing 属性
font 字段 SHALL 支持 line_spacing 属性,控制行距倍数。
#### Scenario: 设置行距倍数
- **WHEN** 元素定义 font: {line_spacing: 1.5}
- **THEN** 系统将行距设置为 1.5 倍
#### Scenario: line_spacing 为 1.0
- **WHEN** 元素定义 font: {line_spacing: 1.0}
- **THEN** 系统使用单倍行距
#### Scenario: line_spacing 未定义
- **WHEN** 元素定义 font: {size: 18}(未定义 line_spacing
- **THEN** 系统使用继承或默认的行距设置
### Requirement: 元素 font 必须支持 space_before 属性
font 字段 SHALL 支持 space_before 属性,控制段前间距(单位:磅)。
#### Scenario: 设置段前间距
- **WHEN** 元素定义 font: {space_before: 12}
- **THEN** 系统将段前间距设置为 12 磅
#### Scenario: space_before 为 0
- **WHEN** 元素定义 font: {space_before: 0}
- **THEN** 系统不添加段前间距
#### Scenario: space_before 未定义
- **WHEN** 元素定义 font: {size: 18}(未定义 space_before
- **THEN** 系统使用继承或默认的段前间距
### Requirement: 元素 font 必须支持 space_after 属性
font 字段 SHALL 支持 space_after 属性,控制段后间距(单位:磅)。
#### Scenario: 设置段后间距
- **WHEN** 元素定义 font: {space_after: 12}
- **THEN** 系统将段后间距设置为 12 磅
#### Scenario: space_after 为 0
- **WHEN** 元素定义 font: {space_after: 0}
- **THEN** 系统不添加段后间距
#### Scenario: space_after 未定义
- **WHEN** 元素定义 font: {size: 18}(未定义 space_after
- **THEN** 系统使用继承或默认的段后间距
### Requirement: 元素 font 必须支持 baseline 属性
font 字段 SHALL 支持 baseline 属性控制文本基线位置normal、superscript、subscript
#### Scenario: 设置为上标
- **WHEN** 元素定义 font: {baseline: "superscript"}
- **THEN** 系统将文本设置为上标
#### Scenario: 设置为下标
- **WHEN** 元素定义 font: {baseline: "subscript"}
- **THEN** 系统将文本设置为下标
#### Scenario: 设置为正常基线
- **WHEN** 元素定义 font: {baseline: "normal"}
- **THEN** 系统使用正常基线位置
#### Scenario: baseline 未定义
- **WHEN** 元素定义 font: {size: 18}(未定义 baseline
- **THEN** 系统使用正常基线位置
#### Scenario: baseline 值无效
- **WHEN** 元素定义 font: {baseline: "invalid"}
- **THEN** 系统抛出 ERROR提示 baseline 必须是 normal、superscript 或 subscript
### Requirement: 元素 font 必须支持 caps 属性
font 字段 SHALL 支持 caps 属性控制文本大小写转换normal、allcaps、smallcaps
#### Scenario: 设置为全大写
- **WHEN** 元素定义 font: {caps: "allcaps"}
- **THEN** 系统将文本转换为大写
#### Scenario: 设置为小型大写
- **WHEN** 元素定义 font: {caps: "smallcaps"}
- **THEN** 系统将文本转换为小型大写字母
#### Scenario: 设置为正常大小写
- **WHEN** 元素定义 font: {caps: "normal"}
- **THEN** 系统保持文本原始大小写
#### Scenario: caps 未定义
- **WHEN** 元素定义 font: {size: 18}(未定义 caps
- **THEN** 系统保持文本原始大小写
#### Scenario: caps 值无效
- **WHEN** 元素定义 font: {caps: "invalid"}
- **THEN** 系统抛出 ERROR提示 caps 必须是 normal、allcaps 或 smallcaps
### Requirement: 多行文本必须将所有属性应用到每个段落
当文本内容包含换行符时,系统 SHALL 将所有字体属性(包括扩展属性)应用到文本框中的每个段落。
#### Scenario: 多行文本应用扩展属性
- **WHEN** 文本内容包含换行符且定义 font: {size: 12, underline: true, line_spacing: 1.5}
- **THEN** 系统将所有属性size、underline、line_spacing应用到所有段落
#### Scenario: 多行文本每个段落样式一致
- **WHEN** 文本包含多个换行符且定义了 font 属性
- **THEN** 每个段落的字体样式都应一致
### Requirement: 扩展属性必须支持继承机制
扩展属性 SHALL 遵循与基础属性相同的继承机制parent → 当前定义 → fonts_default → 系统默认。
#### Scenario: 扩展属性从 parent 继承
- **WHEN** parent 定义 underline: true当前定义未指定 underline
- **THEN** 元素使用 underline: true从 parent 继承)
#### Scenario: 扩展属性从 fonts_default 继承
- **WHEN** fonts_default 定义 line_spacing: 1.5,元素未指定 line_spacing
- **THEN** 元素使用 line_spacing: 1.5(从 fonts_default 继承)
#### Scenario: 当前定义覆盖继承的扩展属性
- **WHEN** parent 定义 space_before: 12当前定义 space_before: 24
- **THEN** 元素使用 space_before: 24当前定义覆盖