全屏滑条统一路径+对比色(112/115) + 字体索引+查列表+丢失降级(113) + 文档刷新(114) + svcd CLI文档+mips-repo拆bins/mpk(116)
This commit is contained in:
1 parent
b75ecce5de
commit
19a001f007
22 files changed
+666
-129
No files matched your search
@@ -117,6 +117,54 @@ int meow_font_config_multifont(int on,
|
||||
int meow_font_import_zip(const char *zip_path); /* TODO:MeowPanel */
|
||||
int meow_font_export_zip(const char *family, const char *out_zip); /* TODO:MeowPanel */
|
||||
|
||||
/* ================================================================== */
|
||||
/* M2.58 字体索引 + 应用字库查询(规格 §5.7:索引文件 / 查列表 / 丢失降级默认) */
|
||||
/* ================================================================== */
|
||||
/* 系统字体列表的持久化快照 = TF 卡 <card_root>/MeowOS/config/fonts/index(CSV,每套一条:
|
||||
* "family","weight","path","label","tier",glyph_count
|
||||
* path = 卡根相对 font.png(如 MeowOS/fonts/misans/regular/font.png)
|
||||
* label = 显示名(含字重 + 尺寸标记,如 `MiSans Regular(common≈4k)`)
|
||||
* tier = common|gbk|full(档位,信息用 + 驱动按需加载)
|
||||
* launcher 扫描 MeowOS/fonts/<family>/<weight>/ 后写该文件(覆盖,含默认行 index0);
|
||||
* SDK 侧 meow_font_get_available_count()/enumerate() 只从这个文件读,不依赖 launcher 内存数组;
|
||||
* 无卡/无 index → 仅 1 项板载默认(family=default)。 */
|
||||
#define MEOW_FONT_INDEX_REL "MeowOS/config/fonts/index"
|
||||
|
||||
/* 权威列表数据模型(SDK 侧快照,枚举时填充;规格 §5.7.1)。 */
|
||||
#ifndef MEOW_FONT_INFO_DEFINED
|
||||
#define MEOW_FONT_INFO_DEFINED
|
||||
typedef struct meow_font_info {
|
||||
char family[64]; /* family slug = MeowOS/fonts/<family>/ 一级目录名 */
|
||||
char name[64]; /* 显示名(index 无单列 → 回退 family) */
|
||||
char weight[32]; /* weight slug(regular|bold|…,缺省 regular) */
|
||||
char tier[8]; /* 档位 common|gbk|full(info 用) */
|
||||
int glyph_count; /* font.json glyph_count(info 用) */
|
||||
char label[128]; /* index 显示名(含字重 + 尺寸标记) */
|
||||
int size_list[16]; /* 原生字号表(index 无 → 空) */
|
||||
int size_count; /* 有效字号数 */
|
||||
int bit_depth; /* 4|8(index 无 → 0) */
|
||||
char path_png[320]; /* 卡根相对 MeowOS/fonts/<family>/<weight>/font.png */
|
||||
} meow_font_info;
|
||||
#endif
|
||||
|
||||
/* 卡根:env MEOW_CARD_ROOT 优先,否则默认 /usr/data/mnt/sd_0。 */
|
||||
const char *meow_font_card_root(void);
|
||||
/* <card_root>/MeowOS/config/fonts/index 绝对路径写入 out;0=成功。 */
|
||||
int meow_font_index_path(char *out, int olen);
|
||||
/* 读 index → 填充 out 数组(最多 max 条),返回「总条数」(无 index/不可读/空 → 1=合成默认行)。
|
||||
* 注意 out[i].path_png 为「卡根相对」路径,需经卡根解析为绝对路径再使用。 */
|
||||
int meow_font_index_load(meow_font_info *out, int max);
|
||||
|
||||
/* 应用可读 TF 卡字体列表(规格 §5.7.2):
|
||||
* - get_available_count():可用字库数(含默认;无卡 → 1)。
|
||||
* - enumerate(idx, out):按序号取,越界返回 0;idx=0=默认行(family=default)。
|
||||
* - select_by_id(id):id=0 跟随系统默认(font.file,经 env MEOW_FONT_PNG/IDX);
|
||||
* id>0 会话内固定用该套;该套字库缺失 → 降级默认(不丢请求)+ WARN 日志
|
||||
* (meow_log→app 日志)。成功 0,越界负值。 */
|
||||
int meow_font_get_available_count(void);
|
||||
int meow_font_enumerate(int idx, meow_font_info *out);
|
||||
int meow_font_select_by_id(int id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
Binary file not shown.
@@ -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 失败 → 仅默认字体)。 */
|
||||
|
||||
Reference in new issue
Block a user