全屏滑条统一路径+对比色(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
@@ -22,6 +22,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h> /* access():字库缺失判定用 */
|
||||
|
||||
/* ---------------- 最小 zlib ABI 声明(与 libz.a 匹配,mipsel 32-bit unsigned long=4B) ------- */
|
||||
typedef unsigned char mzf_Bytef;
|
||||
@@ -721,3 +722,196 @@ int meow_font_config_multifont(int on,
|
||||
if (distinct) *distinct = d_n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
/* M2.58 字体索引 + 应用字库查询(规格 §5.7:索引文件 / 查列表 / 丢失降级默认) */
|
||||
/* ================================================================== */
|
||||
/* SDK 可选日志:SDK 链 meow_log 强符号(→app 日志);launcher 无 meow_log(弱符号 → NULL,
|
||||
* 静默跳过)——避免 meow_font.o 依赖 SDK,launcher 链接不至于为未定义 meow_log 而失败。 */
|
||||
extern void meow_log(int lvl, const char *fmt, ...) __attribute__((weak));
|
||||
#define MEOW_FONT_INDEX_MAX 32 /* index 条数上限(实际 ≤17,留余量) */
|
||||
|
||||
#define MEOW_FONT_DEF_PNG "/usr/data/mnt/sd_0/MeowOS/fonts/default/regular/font.png"
|
||||
#define MEOW_FONT_DEF_IDX "/usr/data/mnt/sd_0/MeowOS/fonts/default/regular/font.idx"
|
||||
#define MEOW_FONT_SYS_PNG "/usr/share/meowos/font/font.png"
|
||||
#define MEOW_FONT_SYS_IDX "/usr/share/meowos/font/font.idx"
|
||||
|
||||
const char *meow_font_card_root(void)
|
||||
{
|
||||
const char *e = getenv("MEOW_CARD_ROOT");
|
||||
return (e && e[0]) ? e : "/usr/data/mnt/sd_0";
|
||||
}
|
||||
|
||||
int meow_font_index_path(char *out, int olen)
|
||||
{
|
||||
if (!out || olen <= 0) return -1;
|
||||
snprintf(out, (size_t)olen, "%s/%s", meow_font_card_root(), MEOW_FONT_INDEX_REL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 合成「板载默认」条目(index0;无卡/无 index 时唯一项)。 */
|
||||
static void meow_font_default_entry(meow_font_info *out)
|
||||
{
|
||||
if (!out) return;
|
||||
memset(out, 0, sizeof *out);
|
||||
snprintf(out->family, sizeof out->family, "default");
|
||||
snprintf(out->name, sizeof out->name, "默认字体");
|
||||
snprintf(out->weight, sizeof out->weight, "regular");
|
||||
snprintf(out->tier, sizeof out->tier, "common");
|
||||
out->glyph_count = 0;
|
||||
snprintf(out->label, sizeof out->label, "默认字体 Regular(common)");
|
||||
snprintf(out->path_png, sizeof out->path_png, "MeowOS/fonts/default/regular/font.png");
|
||||
}
|
||||
|
||||
/* CSV 单字段读取(支持双引号包裹 + 内嵌双引号转义)。p 走到下一字段/行尾。 */
|
||||
static int csv_field(const char **pp, char *out, int olen)
|
||||
{
|
||||
const char *p = *pp;
|
||||
if (!out || olen <= 0) return 0;
|
||||
int o = 0;
|
||||
if (*p == '"') {
|
||||
p++;
|
||||
while (*p && o < olen - 1) {
|
||||
if (*p == '"') {
|
||||
if (p[1] == '"') { out[o++] = '"'; p += 2; continue; }
|
||||
p++; /* 结束引号 */
|
||||
break;
|
||||
}
|
||||
out[o++] = *p++;
|
||||
}
|
||||
if (*p == ',') p++;
|
||||
else if (*p == '\r' || *p == '\n') { /* 行尾,由外层清理 */ }
|
||||
} else {
|
||||
while (*p && *p != ',' && *p != '\r' && *p != '\n' && o < olen - 1)
|
||||
out[o++] = *p++;
|
||||
if (*p == ',') p++;
|
||||
}
|
||||
out[o] = 0;
|
||||
*pp = p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 有界复制(字符串入 dst≤dlen 且保证 NUL;避免 -Wformat-truncation 之类告警)。 */
|
||||
static void fcpy(char *dst, int dlen, const char *src)
|
||||
{
|
||||
if (dlen <= 0) return;
|
||||
size_t n = src ? strlen(src) : 0;
|
||||
if (n >= (size_t)dlen) n = (size_t)dlen - 1;
|
||||
memcpy(dst, src, n);
|
||||
dst[n] = 0;
|
||||
}
|
||||
|
||||
/* 解析一行 index(CSV 6 字段)。成功填 info 并返回 1;path 为空 → 0(跳过)。 */
|
||||
static int meow_font_parse_index_line(char *line, meow_font_info *info)
|
||||
{
|
||||
if (!line || !info) return 0;
|
||||
const char *p = line;
|
||||
char f[6][360];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (!csv_field(&p, f[i], (int)sizeof f[i])) return 0;
|
||||
if (!f[i][0]) return 0;
|
||||
}
|
||||
memset(info, 0, sizeof *info);
|
||||
fcpy(info->family, sizeof info->family, f[0]);
|
||||
fcpy(info->name, sizeof info->name, f[0]); /* index 无单列 name → 回退 family */
|
||||
fcpy(info->weight, sizeof info->weight, f[1]);
|
||||
fcpy(info->path_png, sizeof info->path_png, f[2]);
|
||||
fcpy(info->label, sizeof info->label, f[3]);
|
||||
fcpy(info->tier, sizeof info->tier, f[4]);
|
||||
info->glyph_count = atoi(f[5]);
|
||||
return info->path_png[0] ? 1 : 0;
|
||||
}
|
||||
|
||||
int meow_font_index_load(meow_font_info *out, int max)
|
||||
{
|
||||
if (!out || max <= 0) return 0;
|
||||
char path[450];
|
||||
if (meow_font_index_path(path, sizeof path) != 0) return 0;
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f) { meow_font_default_entry(&out[0]); return 1; } /* 无卡/无 index → 仅板载默认 */
|
||||
int n = 0, total = 0;
|
||||
char line[1024];
|
||||
while (fgets(line, sizeof line, f)) {
|
||||
char *s = line;
|
||||
while (*s == ' ' || *s == '\t') s++;
|
||||
if (!*s || *s == '\n' || *s == '\r' || *s == '#') continue; /* 忽略空行/注释 */
|
||||
meow_font_info tmp;
|
||||
if (!meow_font_parse_index_line(s, &tmp)) continue;
|
||||
total++;
|
||||
if (n < max) { out[n] = tmp; n++; }
|
||||
}
|
||||
fclose(f);
|
||||
if (total == 0) { meow_font_default_entry(&out[0]); return 1; }
|
||||
return total;
|
||||
}
|
||||
|
||||
int meow_font_get_available_count(void)
|
||||
{
|
||||
meow_font_info buf[1];
|
||||
return meow_font_index_load(buf, 1); /* max=1:只统计总数,不要求全填 */
|
||||
}
|
||||
|
||||
int meow_font_enumerate(int idx, meow_font_info *out)
|
||||
{
|
||||
if (!out || idx < 0) return 0;
|
||||
meow_font_info buf[MEOW_FONT_INDEX_MAX];
|
||||
int n = meow_font_index_load(buf, MEOW_FONT_INDEX_MAX);
|
||||
if (idx >= n) return 0;
|
||||
memcpy(out, &buf[idx], sizeof *out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 相对路径按卡根解析为绝对路径(绝对路径原样返回)。 */
|
||||
static void font_abs_path(const char *rel, char *out, int olen)
|
||||
{
|
||||
if (!rel || !rel[0]) { if (olen > 0) out[0] = 0; return; }
|
||||
if (rel[0] == '/') { snprintf(out, (size_t)olen, "%s", rel); return; }
|
||||
snprintf(out, (size_t)olen, "%s/%s", meow_font_card_root(), rel);
|
||||
}
|
||||
|
||||
/* 由 png 绝对路径派生同目录 font.idx(.png → .idx)。0=成功。 */
|
||||
static int font_idx_from_png(const char *png, char *out, int olen)
|
||||
{
|
||||
if (!png || olen <= 0) return -1;
|
||||
snprintf(out, (size_t)olen, "%s", png);
|
||||
size_t n = strlen(out);
|
||||
if (n > 4 && !strcmp(out + n - 4, ".png")) {
|
||||
out[n-4]='.'; out[n-3]='i'; out[n-2]='d'; out[n-1]='x'; out[n]=0;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 装载系统默认字体(跟随 font.file,经 env MEOW_FONT_PNG/IDX → 卡默认 → 固件)。
|
||||
* 与 SDK meow_ui_gfx load_font 的优先级一致;app 经 select_by_id(0) 或任何降级回退时走此路径。 */
|
||||
static int meow_font_load_system_default(void)
|
||||
{
|
||||
const char *ep = getenv("MEOW_FONT_PNG");
|
||||
const char *ei = getenv("MEOW_FONT_IDX");
|
||||
char idxbuf[400];
|
||||
if (ep && ep[0]) {
|
||||
if (!ei || !ei[0]) {
|
||||
if (font_idx_from_png(ep, idxbuf, sizeof idxbuf) != 0) ei = NULL;
|
||||
else ei = idxbuf;
|
||||
}
|
||||
if (ei && meow_font_load(ep, ei) == 0) return 0;
|
||||
}
|
||||
if (meow_font_load(MEOW_FONT_DEF_PNG, MEOW_FONT_DEF_IDX) == 0) return 0;
|
||||
if (meow_font_load(MEOW_FONT_SYS_PNG, MEOW_FONT_SYS_IDX) == 0) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int meow_font_select_by_id(int id)
|
||||
{
|
||||
if (id == 0) return meow_font_load_system_default(); /* 跟随系统默认(font.file) */
|
||||
meow_font_info info;
|
||||
if (!meow_font_enumerate(id, &info)) return -1; /* 越界 → 负值 */
|
||||
if (!info.path_png[0]) return -1;
|
||||
char png[400], idx[400];
|
||||
font_abs_path(info.path_png, png, sizeof png);
|
||||
if (font_idx_from_png(png, idx, sizeof idx) != 0) return -1;
|
||||
if (access(png, R_OK) == 0 && meow_font_load(png, idx) == 0) return 0;
|
||||
/* 字库缺失 → 降级默认(不丢请求)+ WARN(app 日志;meow_log 为 SDK 统一日志) */
|
||||
if (meow_log) meow_log(2 /* MEOW_LOG_WARN */, "font %s missing, fallback default", png);
|
||||
return meow_font_load_system_default();
|
||||
}
|
||||
Reference in new issue
Block a user