215: meow_font.c 流式分块解码(gbk峰值40→23.5MB, 逐字节校验一致) + 多字体槽5→4+16MB驻留预算; 量化: gbk稳态驻留17.3MB vs common 4.2MB(OOM主因); meow_font.a→67113c03 meow_ui.a→223d5401 216: bootmenu让位(sysui在则start launcher让位, 不在则exec兜底) + S70预置launcher.conf enabled=1(+旧设备升级迁移); launcher崩溃可自动拉起; bootmenu 4441822d / S70 e435affc / S90 e0ace111 216注: S70早启动与选单共存为真机重点观察项
175 lines
11 KiB
C
175 lines
11 KiB
C
#ifndef MEOW_FONT_H
|
||
#define MEOW_FONT_H
|
||
/*
|
||
* meow_font.h — MeowOS 预渲染位图字体运行时(独立、可复用,不绑定启动器)。
|
||
*
|
||
* 数据来源:由 gen/gen_font.py 生成的 font.png(灰度 PNG,bit depth 4|8,含各字号面)
|
||
* + font.idx(索引:头部 + 每面元数据 + 每字符 16B 记录)。
|
||
*
|
||
* 设备端加载:模块内建最小 PNG 解码(仅支持灰度非隔行)经 zlib inflate + 反滤波还原像素,
|
||
* 无需 libpng;交叉链接 musl 静态 libz.a。像素面按 depth=4|8 打包存储,取像素时按 nibble 解包。
|
||
*
|
||
* 绘制模型:drawtext(fb, x, y, utf8, color, size);(x,y)=行首「升线(top)」锚点;
|
||
* baseline = y + ascent;每字形 blit 于 (x + pen + dx, y + dy);pen 累加 advance。
|
||
* color 为 565 位 RGB(R 在 bit15..11,G bit10..5,B bit4..0),与 launcher 一致。
|
||
* 无字回退:缺码位画空心方块(tofu)并前进空格宽度。
|
||
*
|
||
* 字号:字库含若干原生面(如 28、20)。drawtext 请求 size 时先找精确匹配面;
|
||
* 若无则就近取一面做最近邻缩放(最优仍用原生字号)。
|
||
*/
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* 设置 framebuffer 几何:宽/高(像素)与每行字节数(如 480*2)。绘制前调用一次。 */
|
||
void meow_font_set_fb(unsigned fb_w, unsigned fb_h, unsigned pitch_bytes);
|
||
|
||
/* 加载字库(全部字号)。成功返回 0,失败返回负值。可重复调用(先卸载旧的)。 */
|
||
int meow_font_load(const char *png_path, const char *idx_path);
|
||
|
||
/* 释放字库。 */
|
||
void meow_font_unload(void);
|
||
|
||
/* 按档装载大字库(字体档位分层,见 MEOWOS_SPEC_REF §5.2/§5.7.8 与 meow_ui.h §10):
|
||
* tier = 0 common≈4k(小/默认)/ 1 gbk≈20k+(大字库)/ 2 full(全,可选)。
|
||
* png/idx 为调用方已按档解析的设备绝对路径(launcher 经 env 注入)。切换时先 unload 旧
|
||
* 再 load 新(释放旧 atlas —— 大字库 GBK 解码约 5-15MB,避免新旧同时驻留内存)。
|
||
* 返回 0 成功,负值失败(失败时旧库已释放,调用方应回退卡默认/固件)。
|
||
* 由 meow_ui_gfx.c 的 meow_font_set_tier() 在档位变化时唤起;meow_font_load() 仍是装载
|
||
* 系统默认(slot0)字库的入口。 */
|
||
int meow_font_reload_tier(int tier, const char *png, const char *idx);
|
||
|
||
/* 某字号是否存在(命中原生面返回 1)。 */
|
||
int meow_font_has_size(int size);
|
||
|
||
/* UTF-8 字符串渲染宽度(px)。字面不存在返回 0。 */
|
||
int meow_font_width_text(const char *utf8, int size);
|
||
|
||
/* 行高(px = ascent + descent)。 */
|
||
int meow_font_line_height(int size);
|
||
int meow_font_ascent(int size);
|
||
|
||
/* 绘制文本:(x,y)=行首升线顶部;color=RGB565。已按 fb_w/fb_h 裁剪。 */
|
||
void meow_font_drawtext(uint16_t *fb, int x, int y, const char *utf8,
|
||
uint16_t color, int size);
|
||
|
||
/* 描边绘制:先以 outline_color 将每字形向 4/8 邻域平移 ol 绘制一圈,再以 color 填充。 */
|
||
void meow_font_drawtext_outline(uint16_t *fb, int x, int y, const char *utf8,
|
||
uint16_t color, uint16_t outline_color, int ol, int size);
|
||
|
||
/* ---- 字符分类器(multi_font 逐字符路由的依据;按 codepoint 归类)---- */
|
||
typedef enum {
|
||
MEOW_FCLS_CJK = 0, /* CJK 表意文字 + 扩展 / 兼容表意(U+3400-4DBF/4E00-9FFF/20000-2FA1F/…) */
|
||
MEOW_FCLS_CJK_SYM = 1, /* 全角/中文标点(U+3000-303F、U+FF00-FFEF、U+2014/2018-201D/2026、U+00B7) */
|
||
MEOW_FCLS_NUM = 2, /* 0-9 */
|
||
MEOW_FCLS_LATIN = 3, /* A-Za-z(基本拉丁字母) */
|
||
MEOW_FCLS_LATIN_SYM = 4, /* 半角标点(ASCII 非字母数字:空格/括号/引号/运算符/控制符) */
|
||
MEOW_FCLS_OTHER = 5, /* 其他(假名/韩文/他文字/扩展区等) */
|
||
MEOW_FCLS_COUNT = 6
|
||
} meow_fclass;
|
||
|
||
/* 把一个 codepoint 归类为上述之一。 */
|
||
int meow_font_class_of(uint32_t cp);
|
||
|
||
/* 校验码位是否在「将用于渲染它的字库」中存在字形(1=有,0=缺字/字库未加载→渲染为豆腐)。
|
||
* multi_font 开启时按分类路由到对应字库,关闭时仅查全局字库(slot 0)。 */
|
||
int meow_font_has_glyph(uint32_t cp);
|
||
|
||
/* ---- 多字体(MEOW_FCLS* 逐字符路由)----
|
||
* 槽位模型:slot 0 = meow_font_load() 装载的全局/默认字库(font.file);额外字库经
|
||
* meow_font_load_slot() 装载后,用 meow_font_set_class_slot() 把某字符类指到某一槽。
|
||
* meow_font_drawtext/width_text/line_height/... 在 meow_font_enable_multifont(1) 开启时
|
||
* 逐字符分类 → 用该类别对应槽的字库取字形与度量;缺该类别字库/未加载 → 回退 slot 0。
|
||
* 关闭(默认)时一律走 slot 0,行为与单字体完全一致(零额外开销)。
|
||
* 同 family 去重、类别字库 ≤3 套上限 + 打包面内存预算由 meow_font_config_multifont() 统一处理(launcher 与 SDK 共用)。 */
|
||
#define MEOW_MAX_SLOTS 4 /* slot0(全局) + ≤3 套类别字库。真机 56MB:多字体每套字库都驻留整幅
|
||
* 打包面(common≈4.2MiB / gbk≈16.6MiB),5 套太多会叠加 OOM;故硬上限
|
||
* 收到 4,且 meow_font_config_multifont 另按 meow_font.c 内
|
||
* MEOW_MULTIFONT_MEM_BUDGET 做「总打包面字节」预算(超出→新增类别回退全局)。 */
|
||
|
||
int meow_font_load_slot(int slot, const char *png_path, const char *idx_path); /* 0=成功,负值失败 */
|
||
void meow_font_unload_slot(int slot);
|
||
void meow_font_enable_multifont(int on); /* 0=单字体(默认);1=逐字符分类路由 */
|
||
void meow_font_set_class_slot(meow_fclass cls, int slot); /* slot 越界/载入失败 → 该类别回退 slot 0 */
|
||
|
||
/* 一个字符类的候选字库路径(绝对路径,已由调用方按卡根解析;png=NULL/空 = 跟随全局)。 */
|
||
typedef struct {
|
||
const char *png;
|
||
const char *idx;
|
||
} meow_font_class_cfg;
|
||
|
||
/* 依据开关 + 各类候选配置多字体:同 png 路径去重(含与全局相同 → 直接用 slot 0),
|
||
* 独立字库数(含全局)> MEOW_MAX_SLOTS 时截断并置 *truncated=1(此前已装载的保留)。
|
||
* 返回 0 成功,负值失败;*distinct = 实际装载的不同字库数(含全局)。 */
|
||
int meow_font_config_multifont(int on,
|
||
const char *global_png, const char *global_idx,
|
||
const meow_font_class_cfg cfg[MEOW_FCLS_COUNT],
|
||
int *distinct, int *truncated);
|
||
|
||
/* ---- MeowPanel 预留:TF 卡字体库 .zip 导入/导出(TODO,未实现)----
|
||
* 当前仅声明占位,供 MeowPanel 后续接入;不实现、不接 zip 库。
|
||
* 调用方约定(待实现):导入=校验 .zip 内含 font.png+font.idx+font.json 三件套,
|
||
* 校验通过后解压到 TF 卡 MeowOS/fonts/<family>/<weight>/(family/weight 取自 font.json 的
|
||
* family/weight 或 zip 名,缺省 weight=regular;冲突时覆盖需先确认);导出=把
|
||
* MeowOS/fonts/<family>/<weight>/ 三件套打包为 <out_zip>。
|
||
* 目录布局与 font.json schema 见 docs/MEOWOS_SPEC_REF.md §1.2/§5.2。
|
||
* 返回码:MEOW_OK=0 成功,负值错误码(沿用本模块失败负值约定)。 */
|
||
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
|
||
#endif /* MEOW_FONT_H */
|