perf(reader): M31 字体路径记忆化(开书字体查找 35 目录 walk → 1 次 stat)+ 「· 读」徽标即时刷新
字体:find_font_rec/resolve_font 从 reader.c 抽到 app/font_resolve.c 并加进程内记忆化。 只缓存成功路径;命中后仍做一次 access() 校验(字库被删即重扫);没找到不缓存, 用户之后拷入的字库下次开书即可找到。顶栏「刷新」额外调 font_cache_invalidate(), 给「新拷入字库、旧字库仍在」一条显式失效路径。宿主实测:35 目录树 walk 0.026~0.54ms (=300+ 次系统调用)vs 命中 0.001ms(1 次 access);开书路径每次省一次完整 walk。 徽标:副题格式化抽成 shelf_fmt_sub()(扫描与「刚读完置顶」共用一份实现), promote_just_read() 改 ts 后立即重算这本的 sub/sub_folder,「· 读」不再等下次全量刷新。 回归:test_reader_core 6846、shelf_group_smoke 63(+8)、font_resolve_smoke 14 全绿; build_reader.sh 0 warning;扫描缓存/进度语义未改。app.json 0.1.3/code4 → 0.1.4/code5。
This commit is contained in:
1 parent
0b30cdbafb
commit
dc9bfdbdaf
12 files changed
+460
-53
No files matched your search
@@ -69,6 +69,30 @@ void shelf_sort_recent(shelf_book *books, int nbooks)
|
||||
qsort(books, (size_t)nbooks, sizeof(shelf_book), cmp_recent_then_name);
|
||||
}
|
||||
|
||||
/* 重建一本书的两种副题(扫描后与「刚读完置顶」共用同一份格式化逻辑)。
|
||||
* sub = 格式 · 大小 [· 读](format 模式/宫格)
|
||||
* sub_folder = 相对 book.group 第一级之后的子路径 · sub(folder 模式)
|
||||
*/
|
||||
void shelf_fmt_sub(shelf_book *b)
|
||||
{
|
||||
if (!b) return;
|
||||
char sz[24];
|
||||
shelf_fmt_size(sz, sizeof sz, b->size);
|
||||
/* 默认副题:与 M27 前逐字一致(format 模式/宫格都用它)。 */
|
||||
snprintf(b->sub, sizeof b->sub, "%s · %s%s", shelf_fmt_name(b->fmt), sz,
|
||||
b->ts ? " · 读" : "");
|
||||
/* folder 副题:第一级之后的子路径(分类/作品)前置,其余同默认副题。 */
|
||||
const char *rest = strchr(b->group, '/');
|
||||
if (rest) rest++;
|
||||
if (rest && rest[0]) {
|
||||
char pre[100];
|
||||
shelf_copy_utf8(pre, (int)sizeof pre, rest);
|
||||
snprintf(b->sub_folder, sizeof b->sub_folder, "%s · %s", pre, b->sub);
|
||||
} else {
|
||||
snprintf(b->sub_folder, sizeof b->sub_folder, "%s", b->sub);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct scan_ctx {
|
||||
shelf_book *books;
|
||||
int cap;
|
||||
@@ -146,21 +170,7 @@ static void scan_dir(scan_ctx *c, const char *dir, int depth, const char *rel, c
|
||||
b->fmt = f;
|
||||
b->size = (long)st.st_size;
|
||||
b->ts = c->ts_fn ? c->ts_fn(b->path) : 0;
|
||||
char sz[24];
|
||||
shelf_fmt_size(sz, sizeof sz, b->size);
|
||||
/* 默认副题:与 M27 前逐字一致(format 模式/宫格都用它)。 */
|
||||
snprintf(b->sub, sizeof b->sub, "%s · %s%s", shelf_fmt_name(f), sz,
|
||||
b->ts ? " · 读" : "");
|
||||
/* folder 副题:第一级之后的子路径(分类/作品)前置,其余同默认副题。 */
|
||||
const char *rest = strchr(rel, '/');
|
||||
if (rest) rest++;
|
||||
if (rest && rest[0]) {
|
||||
char pre[100];
|
||||
shelf_copy_utf8(pre, (int)sizeof pre, rest);
|
||||
snprintf(b->sub_folder, sizeof b->sub_folder, "%s · %s", pre, b->sub);
|
||||
} else {
|
||||
snprintf(b->sub_folder, sizeof b->sub_folder, "%s", b->sub);
|
||||
}
|
||||
shelf_fmt_sub(b); /* 副题:格式 · 大小 [· 读](+ folder 子路径) */
|
||||
c->n++;
|
||||
}
|
||||
closedir(dp);
|
||||
|
||||
Reference in new issue
Block a user