|
| 1 | +# [0101] Latin Modern Math 数学模式下希腊字母斜体问题修复 |
| 2 | + |
| 3 | +## 相关文档 |
| 4 | +- [dddd.md](dddd.md) - 任务文档模板 |
| 5 | +- [11_41.md](11_41.md) - Latin Modern Math 数学模式下希腊字母斜体问题修复 |
| 6 | +- [11_42.md](11_42.md) - 相关任务文档 |
| 7 | +- [11_44.md](11_44.md) - Unicode 根号下沉问题修复 |
| 8 | +- [11_45.md](11_45.md) - Noto CJK SC 光标倾斜问题修复 |
| 9 | + |
| 10 | +## 任务相关的代码文件 |
| 11 | +- `src/Graphics/Fonts/smart_font.cpp` |
| 12 | +- `tests/Graphics/Fonts/smart_font_test.cpp` |
| 13 | + |
| 14 | +## 如何测试 |
| 15 | + |
| 16 | +### 确定性测试(单元测试) |
| 17 | +```bash |
| 18 | +xmake b smart_font_test |
| 19 | +xmake r smart_font_test |
| 20 | +``` |
| 21 | + |
| 22 | +新增 `test_latin_modern_math_italic_greek` 测试用例,验证在 `Latin Modern Math` 字体、`mathitalic` 模式下: |
| 23 | +- `<alpha>` 映射到 `<#1D6FC>`(数学斜体小写 alpha) |
| 24 | +- `<beta>` 映射到 `<#1D6FD>`(数学斜体小写 beta) |
| 25 | +- `<gamma>` 映射到 `<#1D6FE>`(数学斜体小写 gamma) |
| 26 | + |
| 27 | +### 非确定性测试(文档验证) |
| 28 | +打开 Mogan,在数学模式下输入希腊字母(如 `\alpha`、`\beta`、`\gamma`),使用 Latin Modern Math 字体,确认希腊字母显示为斜体而非正体。 |
| 29 | + |
| 30 | +## 如何提交 |
| 31 | + |
| 32 | +提交前执行以下最少步骤: |
| 33 | + |
| 34 | +```bash |
| 35 | +xmake b smart_font_test |
| 36 | +xmake r smart_font_test |
| 37 | +``` |
| 38 | + |
| 39 | +## What |
| 40 | + |
| 41 | +修复 Latin Modern Math 字体在数学模式下希腊字母显示为正体而非斜体的问题。 |
| 42 | + |
| 43 | +1. 在 `smart_font_rep::resolve` 中,当主字体支持原始希腊字符时,增加判断逻辑:若处于数学模式、字符为希腊字母、且当前 shape 不是 `mathupright`,则优先尝试使用斜体希腊字母码点(U+1D6E2+ 区域)。 |
| 44 | +2. 只有当主字体不支持对应的斜体希腊字母码点时,才回退到原始码点。 |
| 45 | +3. 新增 C++ 单元测试 `test_latin_modern_math_italic_greek`,通过 `advance` 函数验证 alpha、beta、gamma 的映射结果。 |
| 46 | + |
| 47 | +## Why |
| 48 | + |
| 49 | +在数学模式下使用 Latin Modern Math 字体时: |
| 50 | +- 拉丁字母(a-z, A-Z)在 `advance` 中被硬编码映射到 Unicode 数学字母数字符号区(U+1D434+),显示为斜体。 |
| 51 | +- 希腊字母(如 `<alpha>`)不在该硬编码映射中,进入 `resolve` 处理后直接使用基本希腊字母码点(U+03B1+)。Unicode 标准中基本希腊字母区块的默认字形为正体,导致数学模式下希腊字母显示为正体,与拉丁字母的斜体风格不一致。 |
| 52 | + |
| 53 | +对于 `roman` 等 `is_math_family` 字体,`REWRITE_MATH` 机制会将数学字符转换到正确的 Unicode 区域,因此正常。但 Latin Modern Math 未被纳入该机制。 |
| 54 | + |
| 55 | +## How |
| 56 | + |
| 57 | +修改 `resolve` 函数中 `fn[SUBFONT_MAIN]->supports (c)` 分支的逻辑: |
| 58 | + |
| 59 | +```cpp |
| 60 | +bool prefer_italic_greek= false; |
| 61 | +if (math_kind != 0 && is_greek (c) && use_italic_greek (a) && |
| 62 | + shape != "mathupright") { |
| 63 | + string gc= substitute_italic_greek (c); |
| 64 | + if (gc != "" && fn[SUBFONT_MAIN]->supports (gc)) { |
| 65 | + prefer_italic_greek= true; |
| 66 | + } |
| 67 | +} |
| 68 | +if (!prefer_italic_greek) { |
| 69 | + return sm->add_char (tuple ("main"), c); |
| 70 | +} |
| 71 | +``` |
| 72 | + |
| 73 | +当 `prefer_italic_greek` 为 true 时,不直接返回 "main" 子字体,而是继续执行后续逻辑。后续代码(约 1189 行)会检测到希腊字母并通过 `substitute_italic_greek` 将其映射到数学斜体希腊字母区域(U+1D6E2+),从而确保 Latin Modern Math 渲染出斜体字形。 |
| 74 | + |
| 75 | +测试用例通过 `advance` 函数间接验证: |
| 76 | +- `advance` 在处理 `<alpha>` 等希腊字母时会调用 `resolve` |
| 77 | +- `resolve` 中的斜体优先逻辑使最终返回的字符被重写为 `<#1D6FC>` 等斜体码点 |
0 commit comments