全屏滑条统一路径+对比色(112/115) + 字体索引+查列表+丢失降级(113) + 文档刷新(114) + svcd CLI文档+mips-repo拆bins/mpk(116)

This commit is contained in:
MeowOS Dev committed 2026-08-30 14:14:30 +08:00
1 parent b75ecce5de
commit 19a001f007
22 files changed
+666 -129

No files matched your search

+120 -37
View File
@@ -897,7 +897,7 @@ static int meow_font_ensure(void)
return 1;
}
if (have_sel)
logmsg("meow_font: %s load failed, fallback", fpng);
logmsg("meow_font: selected font %s missing, fallback default", fpng); /* 系统日志 */
/* 卡默认 → 固件。 */
if (meow_font_load(UI_FONT_PNG_CARD, UI_FONT_IDX_CARD) == 0 ||
meow_font_load(UI_FONT_PNG_SYS, UI_FONT_IDX_SYS) == 0) {
@@ -906,6 +906,7 @@ static int meow_font_ensure(void)
meow_font_has_size(28), meow_font_has_size(20));
return 1;
}
logmsg("meow_font: all font sources missing, using 5x7 bitmap"); /* WARN:字库不可用 */
return 0;
}
@@ -1082,6 +1083,9 @@ static void meow_font_reload_multifont(void)
cidx[c][n-4]='.'; cidx[c][n-3]='i'; cidx[c][n-2]='d'; cidx[c][n-1]='x'; cidx[c][n]=0;
}
cfg[c].png = cpng[c]; cfg[c].idx = cidx[c];
} else {
/* M2.58:类别字体配置了但缺失 → 该类别回退全局,并记系统 WARN。 */
logmsg("multi_font: class %s font %s missing, fallback global", cls_keys[c], ref);
}
}
}
@@ -1900,10 +1904,84 @@ static int meow_font_probe_weight(const char *dirpath, const char *family, const
return 1;
}
/* M2.58 字体索引:CSV 字段写入(始终双引号包裹,内嵌双引号加倍)。返回写入长度。 */
static int font_index_csvq(char *dst, int olen, const char *s)
{
int o = 0;
if (olen <= 0) return 0;
if (o < olen) dst[o++] = '"';
for (; *s && o < olen - 3; s++) {
if (*s == '"') dst[o++] = '"';
if (o < olen - 2) dst[o++] = *s;
}
if (o < olen) dst[o++] = '"';
dst[o] = 0;
return o;
}
/* 把当前 font_presets* 扫描结果落盘为 <card_root>/MeowOS/config/fonts/index(覆盖)。
* 每套一条 `"family","weight","path","label","tier",glyph_count`;path=卡根相对 font.png。
* 目录不存在则 mkdir -p;无卡(mkdir/fopen 失败)→ 静默放弃(仅内存默认项)。
* 该文件是 SDK meow_font_get_available_count()/enumerate() 的持久数据源(规格 §5.7)。 */
static void meow_font_write_index(const char *card_root)
{
if (!card_root || !card_root[0]) return;
char t1[360], t2[380], base[400], path[420];
snprintf(t1, sizeof t1, "%s/MeowOS", card_root);
snprintf(t2, sizeof t2, "%s/MeowOS/config", card_root);
snprintf(base, sizeof base, "%s/MeowOS/config/fonts", card_root);
/* 无卡(card_root 父目录不存在 → ENOENT)→ 静默放弃:仅内存默认项,不刷系统日志。 */
if (mkdir(t1, 0755) != 0 && errno != EEXIST) {
if (errno != ENOENT) logmsg("fonts: index mkdir fail %s", t1);
return;
}
if (mkdir(t2, 0755) != 0 && errno != EEXIST) { logmsg("fonts: index mkdir fail %s", t2); return; }
if (mkdir(base, 0755) != 0 && errno != EEXIST) { logmsg("fonts: index mkdir fail %s", base); return; }
snprintf(path, sizeof path, "%s/index", base);
FILE *f = fopen(path, "w");
if (!f) { logmsg("fonts: index fopen fail %s", path); return; }
char line[1024];
for (int i = 0; i < font_presets_n; i++) {
const char *fam = font_preset_fams[i] ? font_preset_fams[i] : "default";
const char *wt = font_preset_wts[i] ? font_preset_wts[i] : "regular";
const char *val = font_presets[i] ? font_presets[i] : "MeowOS/fonts/default/regular/font.png";
const char *lbl = font_preset_labels[i] ? font_preset_labels[i] : fam;
const char *tier = font_preset_tiers[i] ? font_preset_tiers[i] : "common";
int o = 0;
o = font_index_csvq(line, sizeof line, fam);
line[o++] = ','; line[o] = 0;
o += font_index_csvq(line + o, sizeof line - (size_t)o, wt);
line[o++] = ','; line[o] = 0;
o += font_index_csvq(line + o, sizeof line - (size_t)o, val);
line[o++] = ','; line[o] = 0;
o += font_index_csvq(line + o, sizeof line - (size_t)o, lbl);
line[o++] = ','; line[o] = 0;
o += font_index_csvq(line + o, sizeof line - (size_t)o, tier);
line[o++] = ','; line[o] = 0;
snprintf(line + o, sizeof line - (size_t)o, "%d\n", font_preset_glyphs[i]);
fputs(line, f);
}
fclose(f);
logmsg("fonts: index written (%d entries) -> %s", font_presets_n, path);
}
/* 扫描 <card_root>/MeowOS/fonts/ 下两级 <family>/<weight>/,重建字体 preset 列表。
* 每个 (family,weight) 组合一套(如 misans/regular、misans/bold);family 级 'default' 由
* 索引 0(默认字体)单独处理,不进循环,避免重复。上限 FONT_PRESETS_MAX
* (1 默认 + ≤16 用户字体)。无卡/无目录时仅默认。 */
* (1 默认 + ≤16 用户字体)。无卡/无目录时仅默认。
*
* M2.58 释放语义(规格 §5.7 需求 4「扫→写 index→释放(或按需读 index)」结论):
* - 持久来源 = <card_root>/MeowOS/config/fonts/index(扫描后由 meow_font_write_index 落盘)。
* SDK 只读该文件,从不依赖本内存数组。
* - font_presets* / *_buf 均为「静态、有界(FONT_PRESETS_MAX=17)、非堆」数组:无内存泄漏,
* 故无运行期 free;「释放」含义 = 两个扫描点(启动 / 进设置页)重建 + 每套固定上限防膨胀。
* - 设置字体列表(font.file / font.class_* 下拉、family→字重子菜单)在本视图内显示时用
* 该数组;离开字体列表视图(run_settings_page 退出)无需显式 free(静态数组),下次
* 进设置/重扫自动重建。
* - ⚠️ 未做「启动后即清空数组」:meow_font_effective_paths_tiered(launch_app 大字库档位
* 选库)与 meow_font_reload_multifont 在运行期持续读 font_presets_n,清空会造成大字库
* 档位退化(red line「保持档位/多字体行为」)。如需「零驻留」,须把这几个核心路径改为
* 直接读 index(较大重构,超出本批边界,留待后续)。 */
static void meow_font_scan_presets_root(const char *card_root)
{
font_presets_n = 0;
@@ -1933,43 +2011,48 @@ static void meow_font_scan_presets_root(const char *card_root)
char root[340];
snprintf(root, sizeof root, "%s/%s", card_root, MEOW_FONTS_CFG);
DIR *d = opendir(root);
if (!d) return; /* 无卡/无字库目录:仅默认 */
struct dirent *de;
while ((de = readdir(d)) && font_presets_n < FONT_PRESETS_MAX) {
if (de->d_name[0] == '.') continue;
if (!strcmp(de->d_name, "default")) continue; /* 默认字体由索引 0 单独处理 */
char fampath[400];
snprintf(fampath, sizeof fampath, "%s/%s", root, de->d_name);
DIR *w = opendir(fampath); /* 一级:<family>/ */
if (!w) continue;
struct dirent *we;
while ((we = readdir(w)) && font_presets_n < FONT_PRESETS_MAX) {
if (we->d_name[0] == '.') continue;
char dirpath[400], label[96], cs[8] = ""; int gc = 0; char wt[32] = "", nm[64] = "";
snprintf(dirpath, sizeof dirpath, "%s/%s", fampath, we->d_name);
if (meow_font_probe_weight(dirpath, de->d_name, we->d_name, label, sizeof label,
cs, sizeof cs, &gc, wt, sizeof wt, nm, sizeof nm) == 0)
continue; /* 缺组件/损坏 → 跳过该套 */
int i = font_presets_n;
snprintf(font_preset_val_buf[i], sizeof font_preset_val_buf[i],
"%s/%s/%s/font.png", MEOW_FONTS_CFG, de->d_name, we->d_name);
snprintf(font_preset_label_buf[i], sizeof font_preset_label_buf[i], "%s", label);
snprintf(font_preset_tier_buf[i], sizeof font_preset_tier_buf[i], "%s", cs[0]?cs:"common");
snprintf(font_preset_fam_buf[i], sizeof font_preset_fam_buf[i], "%s", de->d_name);
snprintf(font_preset_wt_buf[i], sizeof font_preset_wt_buf[i], "%s", wt);
snprintf(font_preset_name_buf[i], sizeof font_preset_name_buf[i], "%s", nm);
font_presets[i] = font_preset_val_buf[i];
font_preset_labels[i] = font_preset_label_buf[i];
font_preset_tiers[i] = font_preset_tier_buf[i];
font_preset_fams[i] = font_preset_fam_buf[i];
font_preset_wts[i] = font_preset_wt_buf[i];
font_preset_names[i] = font_preset_name_buf[i];
font_preset_glyphs[i] = gc;
font_presets_n++;
if (d) { /* 无卡/无字库目录 → 跳过扫描,仅默认 */
struct dirent *de;
while ((de = readdir(d)) && font_presets_n < FONT_PRESETS_MAX) {
if (de->d_name[0] == '.') continue;
if (!strcmp(de->d_name, "default")) continue; /* 默认字体由索引 0 单独处理 */
char fampath[400];
snprintf(fampath, sizeof fampath, "%s/%s", root, de->d_name);
DIR *w = opendir(fampath); /* 一级:<family>/ */
if (!w) continue;
struct dirent *we;
while ((we = readdir(w)) && font_presets_n < FONT_PRESETS_MAX) {
if (we->d_name[0] == '.') continue;
char dirpath[400], label[96], cs[8] = ""; int gc = 0; char wt[32] = "", nm[64] = "";
snprintf(dirpath, sizeof dirpath, "%s/%s", fampath, we->d_name);
if (meow_font_probe_weight(dirpath, de->d_name, we->d_name, label, sizeof label,
cs, sizeof cs, &gc, wt, sizeof wt, nm, sizeof nm) == 0)
continue; /* 缺组件/损坏 → 跳过该套 */
int i = font_presets_n;
snprintf(font_preset_val_buf[i], sizeof font_preset_val_buf[i],
"%s/%s/%s/font.png", MEOW_FONTS_CFG, de->d_name, we->d_name);
snprintf(font_preset_label_buf[i], sizeof font_preset_label_buf[i], "%s", label);
snprintf(font_preset_tier_buf[i], sizeof font_preset_tier_buf[i], "%s", cs[0]?cs:"common");
snprintf(font_preset_fam_buf[i], sizeof font_preset_fam_buf[i], "%s", de->d_name);
snprintf(font_preset_wt_buf[i], sizeof font_preset_wt_buf[i], "%s", wt);
snprintf(font_preset_name_buf[i], sizeof font_preset_name_buf[i], "%s", nm);
font_presets[i] = font_preset_val_buf[i];
font_preset_labels[i] = font_preset_label_buf[i];
font_preset_tiers[i] = font_preset_tier_buf[i];
font_preset_fams[i] = font_preset_fam_buf[i];
font_preset_wts[i] = font_preset_wt_buf[i];
font_preset_names[i] = font_preset_name_buf[i];
font_preset_glyphs[i] = gc;
font_presets_n++;
}
closedir(w);
}
closedir(w);
closedir(d);
}
closedir(d);
/* M2.58:扫描结果落盘为 <card_root>/MeowOS/config/fonts/index(含默认行 index0),
* 作为 SDK meow_font_get_available_count()/enumerate() 的持久数据源;无卡时仅默认 1 行,
* 由 meow_font_write_index 内部 mkdir-fail 静默放弃(此路径不刷屏)。 */
meow_font_write_index(card_root);
}
/* 设备默认卡根扫描(等价现状:无卡时 opendir 失败 → 仅默认字体)。 */