Skip to content

Commit 341695f

Browse files
da-liiiclaude
andcommitted
[0126] 添加任务文档 devel/0126.md
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 5c52c20 commit 341695f

4 files changed

Lines changed: 70 additions & 17 deletions

File tree

devel/0126.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# [0126] 优化 smart_font 字体加载性能
2+
3+
## 1 相关文档
4+
- [dddd.md](dddd.md) - 任务文档模板
5+
6+
## 2 任务相关的代码文件
7+
- `src/Graphics/Fonts/smart_font.cpp`
8+
- `src/Graphics/Fonts/smart_font.hpp`
9+
- `tests/Graphics/Fonts/smart_font_test.cpp`
10+
11+
## 3 如何测试
12+
13+
### 3.1 确定性测试(单元测试)
14+
```bash
15+
xmake b smart_font_test
16+
xmake r smart_font_test
17+
```
18+
19+
### 3.2 非确定性测试(文档验证)
20+
```bash
21+
# 构建并运行字体相关测试,确保所有用例通过
22+
xmake b smart_font_test && xmake r smart_font_test
23+
```
24+
25+
## 4 如何提交
26+
27+
提交前执行以下最少步骤:
28+
29+
```bash
30+
xmake b smart_font_test
31+
xmake r smart_font_test
32+
```
33+
34+
## 5 What
35+
36+
通过缓存避免 smart_font 字体加载过程中的重复函数调用,优化性能。
37+
38+
1. 添加 `maybe_initialize_font` 辅助函数,避免对已初始化的子字体重复调用 `initialize_font`
39+
2. 在构造函数中缓存 `trimmed_tokenize(family, ",")` 结果(`family_tokens`),避免 `resolve(string c)``is_italic_prime` 中重复分割字符串
40+
3. 在构造函数中缓存 `logical_font` 结果(`given_font`),避免 `resolve(c, fam, attempt)` 中重复计算
41+
4. 缓存 `is_italic_prime` 的结果,避免对同一字体的斜体引号判断重复计算
42+
5. 新增 `test_performance``test_math_performance` 回归测试
43+
44+
## 6 Why
45+
46+
在字体加载过程中,通过添加日志发现很多函数会被重复调用。例如解析数学模式下 24 个希腊字母时,`initialize_font` 被调用了 21 次,虽然大部分调用的子字体已经初始化过。`trimmed_tokenize(family, ",")``logical_font` 也在每次 `resolve` 时被重复计算,造成不必要的性能开销。
47+
48+
## 7 How
49+
50+
- `maybe_initialize_font(int nr)`:在调用 `initialize_font` 前检查 `fn[nr]` 是否已初始化,只有未初始化时才执行实际的字体创建逻辑
51+
- `family_tokens`:在 `smart_font_rep` 构造函数中将 `trimmed_tokenize(family, ",")` 结果保存为成员变量,供 `resolve(string c)``is_italic_prime` 直接使用
52+
- `given_font`:在构造函数中将 `logical_font(family, variant, series, rshape)` 结果保存为成员变量,供 `resolve(c, fam, attempt)` 中的 `is_wanted` 调用直接使用
53+
- `is_italic_prime` 缓存:添加 `italic_prime_cached``italic_prime_result` 成员变量,首次计算后缓存结果

src/Graphics/Fonts/smart_font.cpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ bool virtually_defined (string c, string name);
3434
font smart_font_bis (string f, string v, string s, string sh, double sz,
3535
int hdpi, int vdpi);
3636

37-
3837
smart_map
3938
get_smart_map (tree fn) {
4039
string name= recompose (tuple_as_array (fn), "-");
@@ -626,9 +625,9 @@ smart_font_rep::smart_font_rep (string name, font base_fn, font err_fn,
626625
fn[SUBFONT_MAIN] = adjust_subfont (base_fn);
627626
fn[SUBFONT_ERROR]= adjust_subfont (err_fn);
628627
this->copy_math_pars (base_fn);
629-
family_tokens = trimmed_tokenize (family, ",");
630-
given_font = logical_font (family, variant, series, rshape);
631-
italic_prime_cached = false;
628+
family_tokens = trimmed_tokenize (family, ",");
629+
given_font = logical_font (family, variant, series, rshape);
630+
italic_prime_cached= false;
632631
if (shape == "mathitalic" || shape == "mathupright" || shape == "mathshape") {
633632
if (is_math_family (mfam)) {
634633
rshape= "right";
@@ -915,9 +914,9 @@ smart_font_rep::resolve (string c, string fam, int attempt) {
915914
}
916915
array<string> a= trimmed_tokenize (fam, "=");
917916
if (N (a) >= 2) {
918-
fam = a[1];
919-
array<string> b = tokenize (a[0], " ");
920-
bool ok = is_wanted (c, fam, b, given_font);
917+
fam = a[1];
918+
array<string> b = tokenize (a[0], " ");
919+
bool ok= is_wanted (c, fam, b, given_font);
921920
if (!ok) {
922921
return -1;
923922
}
@@ -1060,16 +1059,16 @@ bool
10601059
smart_font_rep::is_italic_prime (string c) {
10611060
if (c != "'" && c != "`") return false;
10621061
if (italic_prime_cached) return italic_prime_result;
1063-
string s= "<#2B9>";
1062+
string s= "<#2B9>";
10641063
if (c == "`") s= "<backprime>";
10651064
bool result= true;
10661065
for (int i= 0; i < N (family_tokens); i++)
10671066
if (resolve (s, family_tokens[i], 1) >= 0) {
10681067
result= false;
10691068
break;
10701069
}
1071-
italic_prime_cached = true;
1072-
italic_prime_result = result;
1070+
italic_prime_cached= true;
1071+
italic_prime_result= result;
10731072
return result;
10741073
}
10751074

src/Graphics/Fonts/smart_font.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,12 @@ struct smart_font_rep : font_rep {
9999
int math_kind;
100100
int italic_nr;
101101

102-
array<font> fn;
103-
smart_map sm;
104-
array<string> family_tokens;
105-
array<string> given_font;
106-
bool italic_prime_cached;
107-
bool italic_prime_result;
102+
array<font> fn;
103+
smart_map sm;
104+
array<string> family_tokens;
105+
array<string> given_font;
106+
bool italic_prime_cached;
107+
bool italic_prime_result;
108108

109109
smart_font_rep (string name, font base_fn, font err_fn, string family,
110110
string variant, string series, string shape, double sz,

tests/Graphics/Fonts/smart_font_test.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,8 @@ TestSmartFont::test_performance () {
177177

178178
void
179179
TestSmartFont::test_math_performance () {
180-
font fn= smart_font ("Latin Modern Math", "rm", "medium", "mathitalic", 10, 600);
180+
font fn=
181+
smart_font ("Latin Modern Math", "rm", "medium", "mathitalic", 10, 600);
181182

182183
// Trigger math character resolutions
183184
string math_text= "<alpha><beta><gamma><delta><epsilon><zeta><eta><theta>"

0 commit comments

Comments
 (0)