将 README.md 拆分为多个专题文档,减少认知负荷: - 用户文档迁移到 docs/ (用户指南、元素、模板、参考等) - 开发文档迁移到 docs/development/ (架构、模块、规范) - README.md 精简至 ~290 行,仅保留概览和导航 - 删除 README_DEV.md,内容已迁移 - 归档 OpenSpec 变更 refactor-docs-progressive-disclosure
145 lines
3.5 KiB
Markdown
145 lines
3.5 KiB
Markdown
# 字体系统实现
|
||
|
||
字体解析和继承链处理的实现。
|
||
|
||
## 职责
|
||
|
||
- 字体引用解析
|
||
- 继承链处理
|
||
- 预设类别映射
|
||
- 循环引用检测
|
||
|
||
## PRESET_FONT_MAPPING
|
||
|
||
预设字体类别映射常量:
|
||
|
||
```python
|
||
PRESET_FONT_MAPPING = {
|
||
'sans': 'Arial',
|
||
'serif': 'Times New Roman',
|
||
'mono': 'Courier New',
|
||
'cjk-sans': 'Microsoft YaHei',
|
||
'cjk-serif': 'SimSun',
|
||
}
|
||
```
|
||
|
||
## FontResolver 类
|
||
|
||
### 初始化
|
||
|
||
```python
|
||
class FontResolver:
|
||
def __init__(self, fonts, fonts_default, scope="document", template_fonts=None):
|
||
"""
|
||
Args:
|
||
fonts: 当前作用域的字体字典
|
||
fonts_default: 当前作用域的默认字体
|
||
scope: 作用域标识 ("document" 或 "template")
|
||
template_fonts: 模板库字体字典(仅文档作用域需要)
|
||
"""
|
||
```
|
||
|
||
### resolve_font()
|
||
|
||
解析字体配置的主入口:
|
||
|
||
```python
|
||
def resolve_font(self, font_config):
|
||
"""解析字体配置(主入口)"""
|
||
if font_config is None:
|
||
return self._get_default_config(set())
|
||
|
||
if isinstance(font_config, str):
|
||
# "@xxx" 格式
|
||
return self._resolve_reference(font_config.strip('@'), set())
|
||
|
||
if isinstance(font_config, dict):
|
||
if 'parent' in font_config:
|
||
# {parent: "@xxx", ...} 格式
|
||
return self._resolve_font_dict(font_config, set())
|
||
else:
|
||
# 独立定义
|
||
return FontConfig(**font_config)
|
||
```
|
||
|
||
### _resolve_reference()
|
||
|
||
解析字体引用:
|
||
|
||
```python
|
||
def _resolve_reference(self, reference, visited):
|
||
"""解析字体引用"""
|
||
if reference in visited:
|
||
raise ValueError(f"检测到字体引用循环: {' -> '.join(visited + [reference])}")
|
||
|
||
visited.add(reference)
|
||
|
||
# 检查作用域
|
||
if reference in self.fonts:
|
||
font_data = self.fonts[reference]
|
||
elif self.template_fonts and reference in self.template_fonts:
|
||
font_data = self.template_fonts[reference]
|
||
else:
|
||
raise ValueError(f"字体配置不存在: @{reference}")
|
||
|
||
return self._build_font_config(font_data, visited)
|
||
```
|
||
|
||
### _resolve_font_dict()
|
||
|
||
解析字体字典:
|
||
|
||
```python
|
||
def _resolve_font_dict(self, font_dict, visited):
|
||
"""解析字体字典"""
|
||
parent_ref = font_dict.get('parent', '').strip('@')
|
||
if parent_ref:
|
||
# 先解析父级
|
||
parent_config = self._resolve_reference(parent_ref, visited.copy())
|
||
# 合并当前属性
|
||
return self._merge_with_parent(font_dict, parent_config)
|
||
|
||
# 独立定义
|
||
return FontConfig(**font_dict)
|
||
```
|
||
|
||
## 字体引用解析逻辑
|
||
|
||
1. 如果 `font_config` 为 None,使用 `fonts_default`
|
||
2. 如果是字符串(`"@xxx"`),解析为整体引用
|
||
3. 如果是字典且包含 `parent`,先解析 `parent` 再覆盖当前属性
|
||
4. 如果是字典且不包含 `parent`,直接使用字典属性
|
||
5. 未定义的属性从 `fonts_default` 继承
|
||
6. 如果 `family` 是预设类别,映射到具体字体名称
|
||
7. 返回完整的 `FontConfig` 对象
|
||
|
||
## 继承链
|
||
|
||
属性继承顺序:
|
||
|
||
```
|
||
parent → 当前属性 → fonts_default → 系统默认
|
||
```
|
||
|
||
## 循环引用检测
|
||
|
||
- 维护已访问集合 `visited`
|
||
- 检测重复引用
|
||
- 最大引用深度限制:10 层
|
||
|
||
## 预设类别映射
|
||
|
||
在 `family` 字段中识别预设类别名称:
|
||
|
||
```python
|
||
if family in PRESET_FONT_MAPPING:
|
||
family = PRESET_FONT_MAPPING[family]
|
||
```
|
||
|
||
## 相关文档
|
||
|
||
- [作用域系统](scope-system.md) - 字体作用域规则
|
||
- [字体主题系统](../../fonts.md) - 用户指南
|
||
|
||
[返回开发文档索引](../README.md)
|