问题:SDK 位图字库(meow_font)只有离散字号档位,全字形 atlas 稳态 17.3MiB (27MB 整机装不下)→ 大字库/大字号必出豆腐。阅读器 R1/R2 的 FreeType 管线已真机验证 (MiSans OTF),本 commit 将其上收 SDK,让任意 App 用上无级字号 + CJK 全字形。 设计(追加式,与位图字库并存): - meow_ui_ft.c(独立 .o):meow_ft_load/unload/loaded/text/width/line_height/ ascender/descender/cache_set_slots/cache_slots/cache_used。底层按 READER_ENGINE_NOTES §5: FT_New_Face(path) 按需读文件(零整载 anon);灰阶 FT_LOAD_RENDER|NO_HINTING|TARGET_LIGHT; glyph LRU key=(px<<32)|cp,默认 512(~0.46MB),可配 256/1024;测宽不栅格化。 - meow_ui_gfx.c 只加两个薄封装 meow_gfx_ft_blend_px/dirty(写 back_buf + 标脏), 使 meow_ui_ft.o 不引入新依赖——「不调 meow_ft_* 的 App 零增量」(freetype 不拉入,已验证)。 - 降级:加载失败/无卡 → meow_ft_loaded()==0 → meow_ft_text 自动改走 meow_ui_text(位图字库, 5x7 兜底),绝不豆腐不崩;meow_ft_width/line_height 降级位图字库度量。 - FreeType 2.14.3 vendor 进 patch_v2/sdk/vendor/(gitignore)+ build_sdk.sh 可复现拉取+裁剪 构建(-DFT_DISABLE_ZLIB/BZIP2/PNG/HARFBUZZ/BROTLI=TRUE,静态 musl),freetype .o 编入 meow_ui.a,App 链接命令不变(meow_ui.a libz.a -lpthread)。 验证: - 宿主 test_meow_ui_ft 5 项全 PASS(加载/渲染像素非空/宽度测量/LRU 淘汰/降级回退)。 - 全量 SDK 回归:widgets/sdk_fixes/dispatch/notif_gesture/overlay_suppress/listvirt/box/anim/ scroll/ime_fix/pinyin/notif_open/sb_collapse/theme/notify_ipc/audio_host/vol/str/config/ sdk_input_keys 全 PASS。 - 交叉 -Wall -Wextra 全 SDK TU 0 warning;qemu-mipsel 冒烟 PASS(mipsel FreeType 真光栅化)。 - meow_ui.a 新 md5 6ff5be9455f9e197b35fa120be012041(未重链不部署 App,四 App 免重链)。 MEOW_APP_SDK.md 补 §10.1 矢量字一节 + 公共头索引/§9 构建约定更新;.gitignore 忽略 patch_v2/sdk/vendor/ 与 test_meow_ui_ft 二进制。
119 lines
7.3 KiB
C
119 lines
7.3 KiB
C
/*
|
||
* meow_ui_font.h — SDK 字体:应用可读 TF 卡字体列表(§5.7)+ 字体分层/大字库(§10)。
|
||
*
|
||
* 原 meow_ui.h 拆分的一部分(font 模块)。字库权威列表 = launcher 扫描落盘的持久文件
|
||
* MeowOS/config/fonts/index(CSV);App 只经本接口读该列表。字体「档位」由 launcher 按
|
||
* app.json 声明的 "fonts:<档>" 注入 MEOW_FONT_TIER;SDK 据档选库(meow_font_reload_tier)。
|
||
*/
|
||
#ifndef MEOW_UI_FONT_H
|
||
#define MEOW_UI_FONT_H
|
||
|
||
#include <stdint.h> /* uint32_t(meow_ft_text color)—— 子头自洽、可单独 include */
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/* ============================================================ */
|
||
/* §5.7 应用可读 TF 卡字体列表(M2.58:字体索引 / 查列表 / 丢失降级默认) */
|
||
/* ============================================================ */
|
||
/* 系统字体管理器的面向应用接口(规格 §5.7.1/§5.7.2):
|
||
* - 权威列表 = launcher 扫描 MeowOS/fonts/<family>/<weight>/ 后落盘的持久文件
|
||
* MeowOS/config/fonts/index(CSV:family,weight,path,label,tier,glyph_count)。
|
||
* app 只经本接口读该列表(不直接拼路径、不依赖 launcher 内存数组)。
|
||
* - 渲染仍走 env MEOW_FONT_PNG/MEOW_FONT_IDX(launcher 注入的「当前生效字体」,
|
||
* 选中字体那一套);本节的 get_available_count/enumerate 只负责「列有哪些库」,
|
||
* select_by_id 负责「app 会话内固定用哪套」。两路明确。
|
||
* - 无卡 / 无 index → 仅 1 项板载默认(family=default)。 */
|
||
#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
|
||
|
||
/* 可用字库数(含默认;无卡 → 1)。 */
|
||
int meow_font_get_available_count(void);
|
||
/* 按序号取:idx=0=默认行(family=default);越界返回 0。 */
|
||
int meow_font_enumerate(int idx, meow_font_info *out);
|
||
/* 选该套为 app 会话默认字体:id=0 跟随系统默认(font.file,经 env);id>0 固定用该套。
|
||
* 该套字库缺失 → 降级默认(不丢请求)+ WARN(meow_log→app 日志)。成功 0,越界负值。 */
|
||
int meow_font_select_by_id(int id);
|
||
|
||
/* ============================================================ */
|
||
/* §10 字体分层 / 大字库(M2.5x:基座声明 + font 域已实现按档装载) */
|
||
/* ============================================================ */
|
||
/* 字体「档位」概念:launcher 按 app.json 声明的字库档("fonts":<档>)向 app 注入
|
||
* MEOW_FONT_TIER=<0|1|2>;SDK(meow_ui_gfx / meow_font 大字库加载)据档选库:
|
||
* MEOW_FONT_TIER_COMMON=0 默认 4K 常用字库;
|
||
* MEOW_FONT_TIER_GBK =1 大字库 GBK;
|
||
* MEOW_FONT_TIER_FULL =2 Full(全字符集)。
|
||
* 大字库生成由 font/gen/gen_font.py --charset 按档产出;按档装载由 meow_font_reload_tier()
|
||
* 实现(先 unload 旧再 load 新,释放旧 atlas 防大字库双驻留)。launcher 经
|
||
* meow_font_effective_paths_tiered() 按档解析大字库绝对路径并注入 MEOW_FONT_PNG/IDX。
|
||
* 既有 meow_font_* 符号(class_of/has_glyph/load_slot/config_multifont…)保留不动。
|
||
* 判缺字:meow_font_has_glyph(cp) 预判当前字库是否含该码位。 */
|
||
#define MEOW_FONT_TIER_COMMON 0
|
||
#define MEOW_FONT_TIER_GBK 1
|
||
#define MEOW_FONT_TIER_FULL 2
|
||
|
||
/* 设当前字体档(0/1/2,越界 clamp 到合法值),返回生效档。
|
||
* meow_ui_gfx.c 定义并触发 meow_font_reload_tier() 真重载(大字库切换释放旧 atlas)。 */
|
||
int meow_font_set_tier(int tier);
|
||
/* 当前字体档(初始 = MEOW_FONT_TIER_COMMON;meow_ui_init 时读 MEOW_FONT_TIER env 对齐)。 */
|
||
int meow_font_tier(void);
|
||
|
||
/* ============================================================ */
|
||
/* §10.1 矢量字(FreeType,2026-09-02 追加)—— 上收阅读器管线到 SDK */
|
||
/* ============================================================ */
|
||
/* 背景:SDK 位图字库只有离散字号档位(meow_font);阅读器 R1/R2 的 FreeType 管线已在真机
|
||
* 验证(MiSans OTF 渲染)。本组 API 把矢量字能力上收 SDK,任何 App 可用:**无级字号 + CJK
|
||
* 全字形**——这是解决大字库豆腐类问题的根(位图全字形 atlas 稳态 17.3MiB 装不下,矢量按需
|
||
* 读文件 + LRU 缓存字形)。与位图字库**并存**:App **显式**调用 meow_ft_* 才走矢量;既有
|
||
* meow_ui_text 路径零改动(默认仍是 meow_font)。 */
|
||
/* 内存纪律(对齐 READER_ENGINE_NOTES §5.1/§5.4):
|
||
* - FT_New_Face(path) 按需读文件(不整载 → 零大块 anon;文件 disk-backed 可回收重读)。
|
||
* - glyph LRU 512(默认,~0.46MB:28px CJK 约 900B/字),可配 256 省内存 / 1024 提命中。
|
||
* - 目标单 App 增量 ≤1.5MB(FreeType 本体按需拉入,App 不调 meow_ft_* 则零增量)。 */
|
||
|
||
/* 载入矢量字体文件(TTF/OTF 绝对路径)。0=成功;重载会先释放旧面 + 清空 glyph 缓存。
|
||
* 失败(路径无效/损坏/无 FreeType)返回负值,meow_ft_loaded()==0,后续 text/width 自动降级
|
||
* 位图字库(meow_font),绝不豆腐不崩。 */
|
||
int meow_ft_load(const char *path);
|
||
/* 释放矢量字体(保留 FreeType 运行时可再载;再调 meow_ft_load 即可)。 */
|
||
void meow_ft_unload(void);
|
||
/* 当前是否已载入矢量字体(0=无 → text/width 走位图字库降级)。 */
|
||
int meow_ft_loaded(void);
|
||
|
||
/* 矢量渲染文本:(x,y)=行首升线顶(同 meow_ui_text;baseline = y + meow_ft_ascender(px));
|
||
* 颜色为 24-bit RGB(内部按当前 back_buf 底色逐像素 blend565 反锯齿);px=字号(无级)。
|
||
* 返回 0=矢量渲染成功;-1=无矢量字体 → 已自动降级 meow_ui_text(位图字库,不出豆腐);
|
||
* -2=未初始化/空串。 */
|
||
int meow_ft_text(int x, int y, const char *utf8, int px, uint32_t color);
|
||
/* 矢量文本宽度(px;advance 累加,不栅格化、不占 LRU 槽);无矢量字体 → 降级 meow_ui_text_width。 */
|
||
int meow_ft_width(const char *utf8, int px);
|
||
/* 行高 / 上伸 / 下伸(px;无矢量字体时 line_height 返回近似、ascender=px、descender=0)。 */
|
||
int meow_ft_line_height(int px);
|
||
int meow_ft_ascender(int px);
|
||
int meow_ft_descender(int px);
|
||
|
||
/* glyph LRU 容量:默认 512;设 256 省内存 / 1024 提命中(越界 clamp 1..4096,实际生效)。 */
|
||
int meow_ft_cache_set_slots(int slots);
|
||
int meow_ft_cache_slots(void);
|
||
/* 当前 LRU 占用条目数(宿主单测 / 诊断用)。 */
|
||
int meow_ft_cache_used(void);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
#endif /* MEOW_UI_FONT_H */
|