Files
MeowOS-For-R3P2/patch_v2/sdk/include/meow_ui_font.h
T
AskaEth 54750a63c5 feat(sdk): SDK 矢量字(meow_ft_*,§10.1)——上收阅读器 FreeType 管线
问题: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 二进制。
2026-09-02 09:51:23 +08:00

119 lines
7.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* 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 */