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,117 @@
# Font Preset
## Purpose
预设字体类别提供系统内置的字体类别名称,用户可以直接使用这些类别名称引用推荐的字体,无需指定具体字体名称。系统将预设类别映射到跨平台通用的推荐字体。
## Requirements
### Requirement: 系统必须支持五种预设字体类别
系统 SHALL 支持以下预设字体类别sans、serif、mono、cjk-sans、cjk-serif。
#### Scenario: 使用 sans 类别
- **WHEN** 元素定义 font: {family: "sans"}
- **THEN** 系统使用 "Arial" 作为字体族
#### Scenario: 使用 serif 类别
- **WHEN** 元素定义 font: {family: "serif"}
- **THEN** 系统使用 "Times New Roman" 作为字体族
#### Scenario: 使用 mono 类别
- **WHEN** 元素定义 font: {family: "mono"}
- **THEN** 系统使用 "Courier New" 作为字体族
#### Scenario: 使用 cjk-sans 类别
- **WHEN** 元素定义 font: {family: "cjk-sans"}
- **THEN** 系统使用 "Microsoft YaHei" 作为字体族
#### Scenario: 使用 cjk-serif 类别
- **WHEN** 元素定义 font: {family: "cjk-serif"}
- **THEN** 系统使用 "SimSun" 作为字体族
### Requirement: 预设类别映射必须使用跨平台通用字体
预设字体类别 SHALL 映射到跨平台通用性最高的字体,确保在不同操作系统上都有较好的显示效果。
#### Scenario: sans 类别映射到 Arial
- **WHEN** 系统解析 family: "sans"
- **THEN** 映射到 "Arial"Windows/macOS/Linux 通用)
#### Scenario: serif 类别映射到 Times New Roman
- **WHEN** 系统解析 family: "serif"
- **THEN** 映射到 "Times New Roman"Windows/macOS/Linux 通用)
#### Scenario: mono 类别映射到 Courier New
- **WHEN** 系统解析 family: "mono"
- **THEN** 映射到 "Courier New"Windows/macOS/Linux 通用)
#### Scenario: cjk-sans 类别映射到微软雅黑
- **WHEN** 系统解析 family: "cjk-sans"
- **THEN** 映射到 "Microsoft YaHei"Windows 常用中文字体)
#### Scenario: cjk-serif 类别映射到宋体
- **WHEN** 系统解析 family: "cjk-serif"
- **THEN** 映射到 "SimSun"Windows 常用中文字体)
### Requirement: 预设类别必须在 family 字段中识别
系统 SHALL 仅在 font 或 header_font 的 family 字段中识别预设类别名称。
#### Scenario: family 字段使用预设类别
- **WHEN** 元素定义 font: {family: "sans"}
- **THEN** 系统识别 "sans" 为预设类别,映射到 "Arial"
#### Scenario: 其他字段不解析预设类别
- **WHEN** 元素定义 font: {size: "sans"}
- **THEN** 系统将 "sans" 作为字符串值,不进行预设类别映射
#### Scenario: 直接使用字体名称
- **WHEN** 元素定义 font: {family: "SimSun"}
- **THEN** 系统使用 "SimSun" 作为字体族,不进行预设类别映射
### Requirement: 预设类别不进行字体验证
系统 SHALL 不验证预设类别映射的字体是否在系统中存在。
#### Scenario: 预设类别字体不存在时行为
- **WHEN** 系统中不存在 Arial 字体
- **THEN** 系统仍将 "sans" 映射到 "Arial",不报错
#### Scenario: PowerPoint 处理字体回退
- **WHEN** PowerPoint 打开包含不存在字体的 PPTX 文件
- **THEN** PowerPoint 自动回退到系统默认字体
### Requirement: 预设类别可以与 fonts 配置结合使用
用户可以在 fonts 配置中使用预设类别,也可以在元素 font 中直接使用。
#### Scenario: fonts 配置中使用预设类别
- **WHEN** metadata 定义 fonts: {body: {family: "sans", size: 18}}
- **THEN** 系统将 family: "sans" 解析为 "Arial"
#### Scenario: 元素直接使用预设类别
- **WHEN** 元素定义 font: {family: "cjk-sans", size: 24}
- **THEN** 系统将 family: "cjk-sans" 解析为 "Microsoft YaHei"
#### Scenario: 预设类别与引用结合
- **WHEN** fonts.title 定义 family: "sans",元素定义 font: "@title"
- **THEN** 元素使用 family: "Arial"(通过 title 配置)