全屏滑条统一路径+对比色(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();
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user