From a2673d5922f63bfd1bf5e5aa7b2414e36bf95e6b Mon Sep 17 00:00:00 2001 From: MeowOS Dev Date: Sun, 30 Aug 2026 11:46:29 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=89=E7=89=B9=E6=80=A7:=20=E5=AD=97?= =?UTF-8?q?=E4=BD=93=E5=88=86=E5=B1=82(gen=5Ffont.py=20--charset=20+=20meo?= =?UTF-8?q?w=5Ffont=5Freload=5Ftier=20+=20font.load=5Ffull=20+=20=E5=B0=BA?= =?UTF-8?q?=E5=AF=B8=E6=A0=87=E8=AE=B0)=20+=20=E5=85=A8=E5=B1=8F=E6=9C=BA?= =?UTF-8?q?=E5=88=B6/=E7=8A=B6=E6=80=81=E6=A0=8F=E6=94=B6=E5=90=88(meow=5F?= =?UTF-8?q?ui=5Fsys/input)=20+=20=E9=80=9A=E7=9F=A5#6=20TF=E8=BD=AC?= =?UTF-8?q?=E5=82=A8(CSV+10MB+=E5=BC=80=E6=9C=BA=E6=B8=85=E6=9D=BF?= =?UTF-8?q?=E8=BD=BD+=E5=86=85=E5=AD=98=E8=A1=A8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MEOW_APP_SDK.md | 2 + docs/MEOWOS_SPEC_REF.md | 8 +- font/gen/gen_font.py | 99 +++++++++- font/meow_font.c | 16 ++ font/meow_font.h | 9 + font/test_multi_font.c | 32 +++ patch_v2/meow_launcherd/meow_font.h | 9 + patch_v2/meow_launcherd/meow_launcherd | Bin 372844 -> 379228 bytes patch_v2/meow_launcherd/meow_launcherd.c | 236 ++++++++++++++++++----- patch_v2/meow_launcherd/meow_notif.c | 197 ++++++++++++++++++- patch_v2/meow_launcherd/meow_notif.h | 14 +- patch_v2/meow_launcherd/meow_settings.c | 4 + patch_v2/meow_launcherd/test_notif_tf.c | 158 +++++++++++++++ patch_v2/sdk/meow_ui.h | 14 +- patch_v2/sdk/meow_ui_gfx.c | 34 ++-- patch_v2/sdk/meow_ui_input.c | 28 ++- patch_v2/sdk/meow_ui_sys.c | 19 +- patch_v2/sdk/meow_ui_sys.h | 20 +- 18 files changed, 819 insertions(+), 80 deletions(-) create mode 100644 patch_v2/meow_launcherd/test_notif_tf.c diff --git a/MEOW_APP_SDK.md b/MEOW_APP_SDK.md index b78ca6c..11a7f50 100644 --- a/MEOW_APP_SDK.md +++ b/MEOW_APP_SDK.md @@ -326,6 +326,8 @@ patch_v2/meow_launcherd/meow_font.a # 复用(静态链接) > **app 字体来源(M2.x 已落地)**:app 若**自带字库**(`load_handle`,见 §5.7.3,**未实现**)则用它;否则 SDK `meow_ui_gfx.c load_font()` **优先读 launcher 注入的环境变量** `MEOW_FONT_PNG`/`MEOW_FONT_IDX`(=系统 `font.file` 当前生效字体,绝对路径)/`MEOW_FONT_APP`(family),无 env 则回退卡默认 `MeowOS/fonts/default/font.png` → 固件。因此**app 未自带字库时跟随系统 `font.file`**,不再硬编码 `MeowAPPs/fonts`。 > > **app 多字体(M2.5x,`display.multi_font`)**:launcher 注入 `MEOW_MULTI_FONT=0/1` 与 6 类 `MEOW_FONT_CLS_<类>_PNG/IDX`(命中则覆盖全局;类值为空=跟随全局不注入)。SDK `meow_ui_gfx` 的 `meow_gfx_load_multifont()` 读 env → 调 `meow_font_config_multifont()`(同 png 去重、≤4 套上限、缺类回退全局)构建**逐字符分类路由**:`meow_font_drawtext/width_text/line_height` 按 `meow_font_class_of(cp)`(`MEOW_FCLS_CJK/_CJK_SYM/_NUM/_LATIN/_LATIN_SYM/_OTHER`)用对应字库取字形与度量;`meow_font_has_glyph(cp)` 可预判缺字。`display.multi_font=0`/无 env → 单字体(现状,零额外开销)。底层接口见 meow_font.h:`meow_font_load_slot`/`meow_font_unload_slot`/`meow_font_enable_multifont`/`meow_font_set_class_slot`/`meow_font_config_multifont`;`MEOW_MAX_SLOTS=5`。 +> +> **app 字体档位(M2.5x,`app.json "fonts"` 声明 + `font.load_full`)**:launcher 按 `app.json "fonts":"common|gbk|full"` 与系统「加载大字库」开关(`font.load_full`,默认 0;开=强制 ≥gbk 档)算出**生效档**,注入 `MEOW_FONT_TIER=<0|1|2>`(0=**common**≈4k 常用 1=**gbk**≈20k+ 大 2=**full** 全/可选),并把 `MEOW_FONT_PNG/IDX` 指向该档字库绝对路径——`meow_font_effective_paths_tiered()` 在卡内 `MeowOS/fonts//` 按 `font.json` 的 `charset`(`common|gbk|full`)选库(gbk 请求接受 gbk/full;full 请求优先 full 再降级 gbk;无匹配回退全局 `font.file`)。SDK `meow_ui_gfx.c load_font()` 载入后,应用可经 `meow_font_tier()` 查询当前档、`meow_font_set_tier()` 切档(触发 `meow_font_reload_tier()` **真重载**:大字库切换先 unload 旧再 load 新,释放旧 atlas,防 GBK/Full 大库双驻留)。**判缺字**:`meow_font_has_glyph(cp)` 预判当前字库是否含该码位(common 小库下缺字→app 回退/提示,避免静默豆腐)。底层接口见 meow_font.h `meow_font_reload_tier`;`font/gen/gen_font.py --charset common|gbk|full` 按档生成 `font.png/font.idx/font.json`(`font.json` 写 `charset`+`glyph_count`)。 --- diff --git a/docs/MEOWOS_SPEC_REF.md b/docs/MEOWOS_SPEC_REF.md index ac932c8..6329186 100644 --- a/docs/MEOWOS_SPEC_REF.md +++ b/docs/MEOWOS_SPEC_REF.md @@ -161,9 +161,9 @@ - **preset 动态化**:启动/进设置页扫描一次 `MeowOS/fonts/*/`,重建「字体文件」下拉(默认字体 + ≤16 套卡内字体;上限防爆)。扫描仅此二时机,勿放热路径。 - **MeowPanel 预留**:`meow_font_import_zip()`/`meow_font_export_zip()` 为 TODO 声明(不实现),供 MeowPanel 后续接入(`.zip` 导入校验→解压到 `MeowOS/fonts//`、导出打包)。 - **多字体(M2.5x,`display.multi_font`)**:按字符类别(CJK/CJK_SYM/NUM/LATIN/LATIN_SYM/OTHER)逐字符路由,每类可各选一套字库(`font.class_*`,默认空=跟随全局 `font.file`);同 family 去重、同时装载不同字体 ≤4 套(超出 WARN「过多不同字体会增内存」并截断);开关关 = 单字体(现状)。详见 §5.7.7「多字体」。 - - **字体档位 / 大字库(M2.5x)**:抽象出**字库大小档位**,让系统/应用/设置页都知道选的是多大字库 `[源:用户 2026-08-30]`。 + - **字体档位 / 大字库(M2.5x,本次实现)**:抽象出**字库大小档位**,让系统/应用/设置页都知道选的是多大字库 `[源:用户 2026-08-30]`。 - 档位枚举:`MEOW_FONT_TIER_COMMON`(**默认 / ≈4k** 码位)/ `MEOW_FONT_TIER_GBK`(**大 / ≈20k+**)/ `MEOW_FONT_TIER_FULL`(**全 / 可选**,码位/体积最大)。 - - `font/gen/gen_font.py` 增 `--charset common|gbk|full` 按档生成 `font.png/font.idx`(现行仅 `--extra` 思路升级为**档位选择**,**本次新增**);每个 `MeowOS/fonts//font.json` 标 `charset` + `glyph_count`(覆盖声明/信息用)。 + - `font/gen/gen_font.py` `--charset common|gbk|full` 按档生成 `font.png/font.idx/font.json`(**已实现**,现行仅 `--extra` 思路升级为**档位选择**);每个 `MeowOS/fonts//font.json` 标 `charset` + `glyph_count`(覆盖声明/信息用,launcher/settings 据此标注与按需装载)。 - **默认用小字库(`common`≈4k)**;仅当 app 声明需大字库(`app.json "fonts":"full"` 或档位)才为该 app 加载大字库(`gbk`≈20k+),见 §5.7.8。 - **系统设置「加载大字库」开关**(`font.load_full`,强制全系统用大字库),见 SYSTEM_SETTINGS §1;**每个字体选项标注字库大小标记**(如 `default(common≈4k)` / `gbk≈20k` / `full`),让用户知道所选字库量级。 - 判缺字:SDK `meow_font_has_glyph(cp)` 预判当前字库是否含该码位(缺字 → app 回退/提示)。 @@ -296,9 +296,9 @@ - **launcher env 注入**(launch_app,app 跟随系统字体):`MEOW_MULTI_FONT=0/1`;`MEOW_FONT_PNG/IDX`(全局,保留);6 类 `MEOW_FONT_CLS_<类>_PNG/IDX`(命中则覆盖全局;类值为空=跟随全局不注入)。SDK `meow_ui_gfx` 读 env 构建同一映射;无 env/关 → 单字体。 - **持久化**:类别字体设置在 settings.conf(板载,无卡也可存),经 `meow_settings_*` 读写,随设置页变更即重配。 - **内存**(推断解码 atlas = `plane_w×plane_h×(depth 4→0.5 / 8→1.0)` 字节;每套另加 glyph 数组 ≈ glyph_count×16B、idx 头保留约 128KB,idx 原始缓冲载毕即释)。实测仓库字库(depth 4):misans(CJK)≈2.44MiB、source_han_sans(CJK)≈2.53MiB、meslo(Latin)≈1.68MiB、google_sans(Latin)≈1.12MiB;按用户估算口径(**depth 8**):CJK ≈ 5-6MB、Latin ≈ 0.3-0.5MB(后者为窄覆盖 Latin 专库)。**典型「1CJK+1Latin」增量**:全局=CJK,另加一套 Latin → 增加 ≈0.3-1.7MB(depth 8 约 0.5MB;实测 depth4 latin 1.1-1.7MB);全局=Latin 另加一套 CJK → 增加 ≈2.4-2.5MB(depth 8 约 5-6MB)。`display.multi_font=0` 时仅全局一套,无任何额外装载。 -- **5.7.8 字体档位分层 / 按需大字库(app 声明 + 系统开关)** `[源:用户 2026-08-30]` +- **5.7.8 字体档位分层 / 按需大字库(app 声明 + 系统开关,本次实现)** `[源:用户 2026-08-30]` - **口径**:默认用**小字库 `common`(≈4k 码位)**;当 app 声明需要**大字库**(如小说阅读器,`app.json` 声明 `"fonts":"full"` 或档位 `"gbk"`/`"common"`)时,才为该 app 加载**大字库 `gbk`(≈20k+)**。档位与 `gen_font.py --charset`、`font.json charset/glyph_count` 见 §5.2「字体档位/大字库」。 - - **app 级 / activity 级**:app 级以 `app.json "fonts":""` 声明;activity 级(如需)以 `route..fonts` 声明(沿用 `route.` 扩展口径)。launcher 启动 app/切 activity 时据声明选加载大/小字库,并经 env 注入(`MEOW_FONT_PNG/IDX` 指向所选档位字库;新增 `MEOW_FONT_TIER` 标注档位)。 + - **app 级 / activity 级**:app 级以 `app.json "fonts":""` 声明(launcher `meow_parse_app_json` 已解析);activity 级(如需)以 `route..fonts` 声明(沿用 `route.` 扩展口径)。launcher 启动 app 时据声明 + `font.load_full` 算**生效档**,经 env 注入(`MEOW_FONT_PNG/IDX` 指向所选档位字库绝对路径;`MEOW_FONT_TIER` 标注档位;launcher `meow_font_effective_paths_tiered` 按卡内 `font.json charset` 选库)。 - **系统设置「加载大字库」**(`font.load_full`,默认 0):开 → **强制全系统用大字库(gbk 档)**,覆盖 app 未声明 + 覆盖默认 `font.file`;关(默认)→ 默认小字库,app 声明才大字库。 - **SDK 判缺字**:`meow_font_has_glyph(cp)` 预判当前字库是否含该码位 → app 据此决定回退/提示(避免 `common` 小字库下静默豆腐或缺字)。 - **⚠️ 与 §5.7.3 冲突**:§5.7.3 `"fonts":[…]` 为**应用自带字库句柄数组**;本小节 `"fonts":"full"` 为**字库档位字符串**。同名键两种语义,需统一解析口径(见 §7 A-14)。 diff --git a/font/gen/gen_font.py b/font/gen/gen_font.py index 91f1139..b3dd6cf 100644 --- a/font/gen/gen_font.py +++ b/font/gen/gen_font.py @@ -44,8 +44,11 @@ idx 二进制布局(little-endian, version=2): +15 u8 dy """ import argparse +import hashlib +import json import os import struct +import unicodedata import zlib from PIL import Image, ImageDraw, ImageFont @@ -96,32 +99,80 @@ def pack_plane_depth(plane_l8, width, height, depth): # -------------------------------------------------------------------------- -# 字符集 +# 字符集(字体档位:common / gbk / full) +# 口径见 docs/MEOWOS_SPEC_REF.md §5.2「字体档位/大字库」与 §5.7.8: +# common ≈ 4k 码位(ASCII + GB2312 常用 + 标点 + --extra) = 现状; +# gbk ≈ 20k+(再并入 CJK 统一表意 U+4E00-9FFF + CJK 符号/全角,含常用简繁/生僻); +# full ≈ 全 Unicode 可渲染区间(gbk + CJK 扩展 A/B-F + 拉丁/希腊/西里尔 + 通用标点,可选)。 +# 每档在产物 font.json 写入 charset + glyph_count(见 write_font_json)。 # -------------------------------------------------------------------------- -def build_charset(extra=""): +CHARSET_TIERS = ("common", "gbk", "full") +CHARSET_ALIAS = {"0": "common", "common": "common", "1": "gbk", "gbk": "gbk", + "2": "full", "full": "full"} + + +def build_charset(tier="common", extra=""): + if tier not in CHARSET_TIERS: + tier = "common" cps = [] def add(cp): - if cp not in cps: + if 0 <= cp <= 0x10FFFF and cp not in cps: cps.append(cp) + # ASCII 可打印字符 for c in range(0x20, 0x7F): add(c) + # GB2312 一/二级常用简体(B0-D7 + D8 常用二级首段) for hi in range(0xB0, 0xD8): for lo in range(0xA1, 0xFF): try: add(ord(bytes([hi, lo]).decode("gb2312"))) except UnicodeDecodeError: pass - for hi in range(0xA1, 0xA4): + # GB2312 符号/全角(A1-A4) + for hi in range(0xA1, 0xA5): for lo in range(0xA1, 0xFF): try: add(ord(bytes([hi, lo]).decode("gb2312"))) except UnicodeDecodeError: pass + if tier in ("gbk", "full"): + # CJK 统一表意(含常用简繁/生僻):U+4E00-9FFF ≈ 2万+ + for cp in range(0x4E00, 0xA000): + add(cp) + # CJK 符号与标点 + 全角形式(补齐 common 未含的) + for cp in range(0x3000, 0x3040): + add(cp) + for cp in range(0xFF00, 0xFFF0): + add(cp) + if tier == "full": + # 拉丁补充 / 希腊 / 西里尔 等常用非 CJK(Latin-1 起已覆盖 AI 常见重音) + for cp in range(0xA0, 0x0530): + add(cp) + # CJK 扩展 A + 兼容表意 + for cp in range(0x3400, 0x4DC0): + add(cp) + for cp in range(0xF900, 0xFB00): + add(cp) + # 通用标点 / 货币等(— … “ ” 等已在 gbk;此处补全) + for cp in range(0x2000, 0x2070): + add(cp) + for cp in range(0x20A0, 0x20D0): + add(cp) + # CJK 扩展 B-F(补充平面) + for cp in range(0x20000, 0x2EBF0): + add(cp) + for cp in range(0x30000, 0x31350): + add(cp) for ch in extra: add(ord(ch)) return sorted(cps) +def charset_glyph_count(cps): + """glyph_count = 字符集码位数(信息用,落 font.json)。""" + return len(cps) + + # -------------------------------------------------------------------------- # 逐字形渲染 # -------------------------------------------------------------------------- @@ -227,6 +278,33 @@ def write_idx(path, bit_depth, faces, glyph_tabs): return len(header) + len(body) +# -------------------------------------------------------------------------- +# font.json(元数据 + 完整性校验;schema 见 docs/MEOWOS_SPEC_REF.md §5.2) +# -------------------------------------------------------------------------- +def write_font_json(out_dir, name, family, tier, glyph_count, sizes, bitdepth, + png_path, idx_path): + def sha256(path): + h = hashlib.sha256() + with open(path, "rb") as f: + for blk in iter(lambda: f.read(1 << 16), b""): + h.update(blk) + return h.hexdigest() + meta = { + "family": family or name, # 同目录名(信息用;扫描端以目录名为 family) + "name": name, # 下拉显示名(缺则回退目录名) + "glyph_count": glyph_count, # 信息用 + "charset": tier, # common|gbk|full(档位;驱动按需加载) + "size_list": sizes, # 原生面字号 + "bit_depth": bitdepth, # 4|8 + "sha256_png": sha256(png_path), # font.png 校验(扫描端仅 WARN) + "sha256_idx": sha256(idx_path), # font.idx 校验(扫描端仅 WARN) + } + jpath = os.path.join(out_dir, "font.json") + with open(jpath, "w", encoding="utf-8") as f: + json.dump(meta, f, ensure_ascii=False, indent=2) + return jpath + + # -------------------------------------------------------------------------- # 主流程 # -------------------------------------------------------------------------- @@ -236,14 +314,18 @@ def main(): ap.add_argument("--sizes", default="28,20") ap.add_argument("--out", required=True) ap.add_argument("--name", default="font") + ap.add_argument("--family", default="", help="font.json family(缺省 = --name;信息用)") + ap.add_argument("--charset", default="common", choices=CHARSET_TIERS, + help="字体档位:common≈4k / gbk≈20k+ / full(可选,默认不推)") ap.add_argument("--bitdepth", type=int, default=4, choices=(4, 8)) ap.add_argument("--extra", default="") args = ap.parse_args() os.makedirs(args.out, exist_ok=True) sizes = [int(s) for s in args.sizes.split(",") if s.strip()] - cps = build_charset(args.extra) - print(f"字符集: {len(cps)} 码位") + tier = CHARSET_ALIAS.get(args.charset, "common") + cps = build_charset(tier, args.extra) + print(f"字符集: {len(cps)} 码位 (charset={tier})") all_planes = [] # (aw, ah, plane_l8 bytes, tab) max_w = 0 @@ -311,10 +393,15 @@ def main(): idx_path = os.path.join(args.out, f"{args.name}.idx") idx_size = write_idx(idx_path, args.bitdepth, face_meta, [p[3] for p in all_planes]) + # ---- font.json(写入 charset + glyph_count + sha256,供扫描端标注档位/大小标记) ---- + jpath = write_font_json(args.out, args.name, args.family, tier, charset_glyph_count(cps), + sizes, args.bitdepth, png_path, idx_path) + png_size = os.path.getsize(png_path) total = png_size + idx_size print(f"\nfont.png {png_size} B") print(f"font.idx {idx_size} B") + print(f"font.json {os.path.getsize(jpath)} B (charset={tier}, glyph_count={len(cps)})") print(f"合计 {total} B = {total/1024:.1f} KiB = {total/1048576:.2f} MiB (预算 2MiB)") diff --git a/font/meow_font.c b/font/meow_font.c index b6b0f17..05f0a34 100644 --- a/font/meow_font.c +++ b/font/meow_font.c @@ -529,6 +529,22 @@ int meow_font_load(const char *png_path, const char *idx_path) { return meow_font_load_slot(0, png_path, idx_path); } +/* ---------------- 按档装载大字库(字体档位分层) ---------------- */ +/* 当前装载档位(0=common 1=gbk 2=full;仅记录,getter 走 meow_ui_gfx.c meow_font_tier) */ +static int g_reload_tier = 0; + +int meow_font_reload_tier(int tier, const char *png_path, const char *idx_path) +{ + if (tier < 0) tier = 0; + if (tier > 2) tier = 2; + if (!png_path || !png_path[0] || !idx_path || !idx_path[0]) return -1; + /* 先 unload 旧(释放旧 atlas——大字库 GBK/Full 解码 5-15MB+,避免新旧同时驻留内存), + * 再 load 新(slot0 = 全局/默认字库)。meow_font_load 内部即 unload+load。 */ + int r = meow_font_load(png_path, idx_path); + if (r == 0) g_reload_tier = tier; + return r; +} + void meow_font_enable_multifont(int on) { g_multifont = on ? 1 : 0; } void meow_font_set_class_slot(meow_fclass cls, int slot) { diff --git a/font/meow_font.h b/font/meow_font.h index 9ceb4bd..11139ce 100644 --- a/font/meow_font.h +++ b/font/meow_font.h @@ -33,6 +33,15 @@ 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); diff --git a/font/test_multi_font.c b/font/test_multi_font.c index dd48e56..9cbd80a 100644 --- a/font/test_multi_font.c +++ b/font/test_multi_font.c @@ -266,6 +266,38 @@ int main(void) { CHECK(distinct == MEOW_MAX_SLOTS, "distinct capped at MEOW_MAX_SLOTS"); } + /* ---- (3) 字体档位分层:meow_font_reload_tier(大字库按档装载/切换)---- + * 用同两套 stub(lat=common 模拟,cjk=gbk 模拟)+ 一个不会释放的 cjk 大面,验证 + * tier>0 装载大字库、切换 unload 旧/load 新、失败回退。 */ + printf("\n== 字体档位分层 meow_font_reload_tier ==\n"); + /* 档位 0=common/1=gbk/2=full(与 meow_ui.h MEOW_FONT_TIER_* 一致;本测试只链 meow_font.h) */ + r = meow_font_reload_tier(0, "/tmp/mf_lat.png", "/tmp/mf_lat.idx"); + CHECK(r == 0, "reload_tier(common, lat) ok"); + CHECK(meow_font_has_glyph('A') == 1, "reload common -> has_glyph(A)=1"); + CHECK(meow_font_has_glyph(0x4E2D) == 0, "reload common -> has_glyph(中)=0 (lat no cjk)"); + CHECK(meow_font_width_text("A", 20) == 10, "reload common -> w(A)=10"); + /* 切到大字库(cjk 槽):应 unload 旧 lat 再 load cjk → '中' 可用、'A' 缺。 */ + r = meow_font_reload_tier(1, "/tmp/mf_cjk.png", "/tmp/mf_cjk.idx"); + CHECK(r == 0, "reload_tier(gbk, cjk) ok"); + CHECK(meow_font_has_glyph(0x4E2D) == 1, "reload gbk -> has_glyph(中)=1"); + CHECK(meow_font_has_glyph('A') == 0, "reload gbk -> has_glyph(A)=0 (cjk lacks lat)"); + CHECK(meow_font_width_text("中", 20) == 30, "reload gbk -> w(中)=30 (cjk slot)"); + CHECK(meow_font_line_height(20) == 33, "reload gbk -> lh(20)=33 (cjk ascent25+desc8)"); + /* 切回 common:再 unload cjk / load lat → 'A' 回来。 */ + r = meow_font_reload_tier(0, "/tmp/mf_lat.png", "/tmp/mf_lat.idx"); + CHECK(r == 0, "reload_tier(common) again ok"); + CHECK(meow_font_has_glyph('A') == 1, "reload back common -> has_glyph(A)=1"); + CHECK(meow_font_has_glyph(0x4E2D) == 0, "reload back common -> has_glyph(中)=0"); + CHECK(meow_font_width_text("A", 20) == 10, "reload back common -> w(A)=10"); + /* Full 档(tier=2)同一套 cjk 作为大字库装载也应成功(档仅记录,装载同路径)。 */ + r = meow_font_reload_tier(2, "/tmp/mf_cjk.png", "/tmp/mf_cjk.idx"); + CHECK(r == 0, "reload_tier(full, cjk) ok"); + CHECK(meow_font_has_glyph(0x4E2D) == 1, "reload full -> has_glyph(中)=1"); + /* 非法参数:NULL/空路径 → 负值(不崩),且字库已被上次 reload 释放(档位装载失败不驻留)。 */ + r = meow_font_reload_tier(1, NULL, NULL); + CHECK(r < 0, "reload_tier(NULL paths) -> negative"); + CHECK(meow_font_has_glyph('A') == 0, "reload failed -> font unloaded (has_glyph=0)"); + printf("\n%s (%d failures)\n", g_fail ? "RESULT: FAIL" : "RESULT: PASS", g_fail); return g_fail ? 1 : 0; } diff --git a/patch_v2/meow_launcherd/meow_font.h b/patch_v2/meow_launcherd/meow_font.h index 9ceb4bd..11139ce 100644 --- a/patch_v2/meow_launcherd/meow_font.h +++ b/patch_v2/meow_launcherd/meow_font.h @@ -33,6 +33,15 @@ 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); diff --git a/patch_v2/meow_launcherd/meow_launcherd b/patch_v2/meow_launcherd/meow_launcherd index 5edf8f0d3fc8f1762d6943693b81dd5e2a993028..398ad7514b53d902643ed653ccd1cfe385839e94 100755 GIT binary patch delta 117337 zcmcejhcX^kU+fq@ntrhLE#cr&8p0E1@2CMfzzW;o0U7qK> z∾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 delta 111414 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πb?PgJtMx&T(5c4=26;|h_ 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 Kdiuo^tik|hmHxv3 diff --git a/patch_v2/meow_launcherd/meow_launcherd.c b/patch_v2/meow_launcherd/meow_launcherd.c index 36482e9..a1470c9 100644 --- a/patch_v2/meow_launcherd/meow_launcherd.c +++ b/patch_v2/meow_launcherd/meow_launcherd.c @@ -791,9 +791,14 @@ static void draw_text(int x, int y, const char *s, int scale, uint32_t color) #define MEOW_FONTS_CFG "MeowOS/fonts" #define FONT_PRESETS_MAX 17 /* 1 默认 + ≤16 卡内字体(防爆) */ static const char *font_presets[FONT_PRESETS_MAX]; /* SC_PRESET 值 = 卡根相对路径 */ -static const char *font_preset_labels[FONT_PRESETS_MAX]; /* SC_PRESET 中文标签 */ +static const char *font_preset_labels[FONT_PRESETS_MAX]; /* SC_PRESET 中文标签(含档位大小标记) */ +/* M2.5x 字体档位:每套的 charset 档("common"/"gbk"/"full",取自 font.json,缺省 "common") + * 与 glyph_count(信息用)。供档位分层装载(meow_font_effective_paths_tiered)与设置页标注。 */ +static const char *font_preset_tiers[FONT_PRESETS_MAX]; +static int font_preset_glyphs[FONT_PRESETS_MAX]; static char font_preset_val_buf[FONT_PRESETS_MAX][320]; /* 值持久存储(指向上面指针数组) */ -static char font_preset_label_buf[FONT_PRESETS_MAX][64]; /* 标签持久存储 */ +static char font_preset_label_buf[FONT_PRESETS_MAX][80]; /* 标签持久存储 */ +static char font_preset_tier_buf[FONT_PRESETS_MAX][8]; /* charset 持久存储 */ static int font_presets_n = 0; /* 运行时动态计数(默认=1,仅"默认字体") */ static int mfont_ready = 0; static int mfont_forced = 0; /* font.file 变更→强制真实(un)load,跳过 SDK 复用捷径 */ @@ -821,6 +826,11 @@ static int meow_font_resolve_path(const char *ref, char *out, int olen) return 0; } +/* 前向声明:meow_font_ensure 在下方 font 区中调用(定义在 meow_font_effective_paths_tiered 处)。 */ +static int meow_font_effective_tier(int app_tier); +static int meow_font_effective_paths_tiered(int tier, char *out_png, int plen, + char *out_idx, int ilen, char *out_family, int flen); + /* 解析 font.file 指向的 png + 派生同目录 idx(font.png → font.idx)。 * 仅当指向的 png 存在(access R_OK)返回 0;否则 -1(交由回退链)。 * 返回 0:out_png/out_idx 已填设备绝对路径。 */ @@ -838,22 +848,25 @@ static int meow_font_resolve_selected(char *out_png, int png_len, char *out_idx, return 0; } -/* 尝试加载字库;成功返回 1。优先级(M2.5x): - * 1) font.file(设置键,真正接管加载;相对路径按卡根解析)→ 存在且能 load 即用; +/* 尝试加载字库;成功返回 1。优先级(M2.5x,font.load_full 已接入): + * 0) 生效档 = font.load_full ? gbk : common(launcher 自身 UI 跟随系统大字库开关); + * 1) 生效字体(tier 解析,tier0 即 font.file 所选;相对路径按卡根解析); * 2) 卡 MeowOS/fonts/default/font.png(默认字库); * 3) 固件 /usr/share/meowos/font/font.png。 * A-1/A-2:SDK meow_ui_init() 已用同一 meow_font.o 加载过(可能成功也可能未成功)。 - * 当 font.file 指向「默认卡字库」或未设置时复用 SDK 已加载状态,避免重复 unload+reload; - * 当 font.file 指向自定义字库时必须显式 load(SDK 只加载默认,不读 font.file)。 - * mfont_forced=1(font.file 变更触发)时无条件真实 reload,跳过上述两条捷径。 + * 当字体指向「默认卡字库」或未设置时复用 SDK 已加载状态,避免重复 unload+reload; + * 当字体指向自定义字库时必须显式 load(SDK 只加载默认,不读 font.file)。 + * mfont_forced=1(font.file/font.load_full 变更触发)时无条件真实 reload,跳过上述捷径。 * 全失败 → mfont_ready=0,ui_draw 回退 5x7 点阵(系统不死)。 */ static int meow_font_ensure(void) { if (mfont_ready && !mfont_forced) return 1; mfont_forced = 0; - char fpng[320], fidx[320]; - int have_sel = (meow_font_resolve_selected(fpng, sizeof fpng, fidx, sizeof fidx) == 0); + char fpng[400], fidx[400], fam[96]; + int tier = meow_font_effective_tier(MEOW_FONT_TIER_COMMON); /* launcher 自身 UI 跟随 load_full */ + int have_sel = (meow_font_effective_paths_tiered(tier, fpng, sizeof fpng, + fidx, sizeof fidx, fam, sizeof fam) == 0); /* SDK 已加载且所选字库为「默认卡字库」(或未设置)→ 复用,避免重复解码。 */ if (meow_gfx_mfont_ready() && (!have_sel || !strcmp(fpng, UI_FONT_PNG_CARD))) { @@ -862,15 +875,15 @@ static int meow_font_ensure(void) return 1; } - /* font.file 优先。 */ + /* 生效字体优先(tier=common 时即 font.file;load_full → 大字库 gbk 档)。 */ if (have_sel && meow_font_load(fpng, fidx) == 0) { mfont_ready = 1; - logmsg("meow_font: loaded font.file %s (%d/%d sizes)", - fpng, meow_font_has_size(28), meow_font_has_size(20)); + logmsg("meow_font: loaded %s (%d/%d sizes), tier=%d", fpng, + meow_font_has_size(28), meow_font_has_size(20), tier); return 1; } if (have_sel) - logmsg("meow_font: font.file %s load failed, fallback", fpng); + logmsg("meow_font: %s load failed, fallback", fpng); /* 卡默认 → 固件。 */ if (meow_font_load(UI_FONT_PNG_CARD, UI_FONT_IDX_CARD) == 0 || meow_font_load(UI_FONT_PNG_SYS, UI_FONT_IDX_SYS) == 0) { @@ -915,17 +928,79 @@ static int meow_font_effective_paths(char *out_png, int plen, char *out_idx, int return -1; } -/* 【tier 选择入口,font 域占位】按字体档位取「当前生效字体」png/idx,供 launch_app 注入 - * MEOW_FONT_PNG/IDX/APP(配合 MEOW_FONT_TIER)。基座只实现 tier=COMMON(=meow_font_effective_paths); - * tier>0 的大字库(GBK/Full)绝对路径由后续 font 代理据此演进填充(约定 MeowOS/fonts// - * /…,或 settings 键 font.tier_gbk / font.tier_full —— 见 MEOW_APP_SDK.md 字体分层)。 - * 未实现前暂回退全局字体。返回 0 成功,-1 无可用。 */ +/* 档位 → font.json charset 字符串名(common/gbk/full)。 */ +static const char *font_tier_charset(int tier) +{ + if (tier >= MEOW_FONT_TIER_FULL) return "full"; + if (tier >= MEOW_FONT_TIER_GBK) return "gbk"; + return "common"; +} + +/* 生效档:app 声明档(0/1/2,越界 clamp)合并「加载大字库」开关(font.load_full)。 + * 开 → 强制 ≥GBK(gbk≈20k 档大字库);关(默认)→ 保持 app 声明(缺省 common≈4k)。 + * 断言:0<=返回<=2。 */ +static int meow_font_effective_tier(int app_tier) +{ + if (app_tier < MEOW_FONT_TIER_COMMON) app_tier = MEOW_FONT_TIER_COMMON; + if (app_tier > MEOW_FONT_TIER_FULL) app_tier = MEOW_FONT_TIER_FULL; + int lf = 0; + if (meow_settings_get_bool("font.load_full", &lf) == 0 && lf) + if (app_tier < MEOW_FONT_TIER_GBK) app_tier = MEOW_FONT_TIER_GBK; + return app_tier; +} + +/* 【tier 选择入口,M2.5x 已实现】按字体档位取「当前生效字体」png/idx,供 launch_app 注入 + * MEOW_FONT_PNG/IDX/APP(配合 MEOW_FONT_TIER)。口径(MEOWOS_SPEC_REF §5.2/§5.7.8): + * - 生效档 = max(app 声明档, font.load_full ? GBK : COMMON):系统「加载大字库」开 → + * 强制 ≥gbk; + * - tier<=common → 走既有 meow_font_effective_paths(font.file/卡默认/固件); + * - tier>0 → 在已扫描的 MeowOS/fonts// 里找 charset 匹配(gbk 请求接受 gbk/full; + * full 请求接受 full)的那套,以其 font.png/idx 绝对路径返回(family = 目录名); + * - 找不到匹配的大字库 → 回退 meow_font_effective_paths(避免 app 直接点到固件小库)。 + * 返回 0 成功(out_png/out_idx/out_family 已填),-1 无可用。 */ static int meow_font_effective_paths_tiered(int tier, char *out_png, int plen, char *out_idx, int ilen, char *out_family, int flen) { - if (tier == MEOW_FONT_TIER_COMMON || tier < MEOW_FONT_TIER_COMMON) + int eff = meow_font_effective_tier(tier); /* 合并 font.load_full:开 → 强制 ≥GBK */ + if (eff <= MEOW_FONT_TIER_COMMON) return meow_font_effective_paths(out_png, plen, out_idx, ilen, out_family, flen); - /* TODO(font 代理):按 tier 解析大字库绝对路径(GBK/Full);暂回退全局(tier0)。 */ + /* 大字库:从扫描结果选 charset 匹配的一套。 + * 打分(高优先):gbk 请求 → gbk=2 > full=1;full 请求 → full=2 > gbk=1(降级可接受)。 */ + const char *want = font_tier_charset(eff); + char ref[320]; + int found_family = -1, best_score = 0; + for (int i = 0; i < font_presets_n; i++) { + const char *cs = font_preset_tiers[i] ? font_preset_tiers[i] : "common"; + int score = 0; + if (!strcmp(cs, want)) score = 2; + else if (!strcmp(cs, "full") || !strcmp(cs, "gbk")) score = 1; /* 降级 */ + if (score > best_score) { best_score = score; found_family = i; } + } + if (found_family >= 0) + snprintf(ref, sizeof ref, "%s", font_presets[found_family]); + if (found_family >= 0) { + /* 相对路径按卡根解析为设备绝对路径(与 meow_font_effective_paths 同源)。 */ + if (meow_font_resolve_path(ref, out_png, plen) != 0) return -1; + if (access(out_png, R_OK) != 0) goto fallback; + snprintf(out_idx, ilen, "%s", out_png); + size_t n = strlen(out_idx); + if (n > 4 && !strcmp(out_idx + n - 4, ".png")) { + out_idx[n-4] = '.'; out_idx[n-3] = 'i'; out_idx[n-2] = 'd'; + out_idx[n-1] = 'x'; out_idx[n] = 0; + } + const char *prefix = "/MeowOS/fonts/"; + const char *p = strstr(out_png, prefix); + if (p) { + const char *q = p + strlen(prefix); + const char *end = strrchr(q, '/'); + int rest = end ? (int)(end - q) : 0; + if (rest > 0 && rest < flen) { memcpy(out_family, q, rest); out_family[rest] = 0; } + else snprintf(out_family, flen, "default"); + } else snprintf(out_family, flen, "default"); + return 0; + } +fallback: + /* 无匹配大字库/不可读 → 回退全局(font.file 所选;其可能是大字库或默认)。 */ return meow_font_effective_paths(out_png, plen, out_idx, ilen, out_family, flen); } @@ -942,7 +1017,10 @@ static void meow_font_reload_multifont(void) int on = 0; meow_settings_get_bool("display.multi_font", &on); char gpng[400], gidx[400], gfam[96]; - if (meow_font_effective_paths(gpng, sizeof gpng, gidx, sizeof gidx, gfam, sizeof gfam) != 0) + /* 全局跟生效档(合并 font.load_full → 大字库),与 meow_font_ensure 同源,避免槽0实际装载与 + * 此处理解不一致(多字体去重以全局 png 为基准)。 */ + if (meow_font_effective_paths_tiered(meow_font_effective_tier(MEOW_FONT_TIER_COMMON), + gpng, sizeof gpng, gidx, sizeof gidx, gfam, sizeof gfam) != 0) return; /* 无全局字体:无法多字体 */ /* 各类候选(静态缓冲保活;config_multifont 同步读取,不持指针) */ static char cpng[MEOW_FCLS_COUNT][400], cidx[MEOW_FCLS_COUNT][400]; @@ -1666,9 +1744,12 @@ static int font_sha_eq(const char *a, const char *b) /* 解析 font.json:提取 name / sha256_png / sha256_idx(文件缺失或解析不出则留空)。 */ static void meow_font_json_probe(const char *json_path, char *name, int nlen, - char *sha_png, int slen, char *sha_idx, int xlen) + char *sha_png, int slen, char *sha_idx, int xlen, + char *charset, int clen, int *glyph_count) { name[0] = 0; sha_png[0] = 0; sha_idx[0] = 0; + if (charset) charset[0] = 0; + if (glyph_count) *glyph_count = 0; FILE *f = fopen(json_path, "r"); if (!f) return; char buf[256]; @@ -1676,14 +1757,39 @@ static void meow_font_json_probe(const char *json_path, char *name, int nlen, if (!name[0]) json_str(buf, "name", name, nlen); if (!sha_png[0]) json_str(buf, "sha256_png", sha_png, slen); if (!sha_idx[0]) json_str(buf, "sha256_idx", sha_idx, xlen); + /* M2.5x 字体档位:charset(common|gbk|full)+ glyph_count(信息用,驱动档位分层/标注)。 */ + if (charset && !charset[0]) { + char v[8] = ""; + if (json_str(buf, "charset", v, sizeof v) > 0 && v[0]) + snprintf(charset, clen, "%s", v); + } + if (glyph_count && *glyph_count == 0) { + char v[16] = ""; + if (json_str(buf, "glyph_count", v, sizeof v) > 0 && v[0]) + *glyph_count = atoi(v); + } } fclose(f); } -/* 探测一个 / 套件是否合法:三件套齐全 → 解析 label + 校验 sha。 - * 返回 1=进列表,0=跳过(缺组件/json 不可读)。sha 失败仅 WARN。 */ +/* 档位大小标记(设置页字体选项标注):common≈4k / gbk≈20k / full。 + * 由 font.json 的 charset + glyph_count 派生;缺 charset 回退 common。 */ +static void font_tier_marker(const char *charset, int glyph_count, char *out, int olen) +{ + const char *tier = (charset && charset[0]) ? charset : "common"; + if (!strcmp(tier, "full")) { snprintf(out, olen, "full"); return; } + if (glyph_count > 0) + snprintf(out, olen, "%s≈%dk", tier, (glyph_count + 500) / 1000); + else + snprintf(out, olen, "%s", tier); +} + +/* 探测一个 / 套件是否合法:三件套齐全 → 解析 label + 档位 + 校验 sha。 + * 返回 1=进列表,0=跳过(缺组件/json 不可读)。sha 失败仅 WARN。 + * 输出:label=显示名+大小标记 `名字(common≈4k)`;charset/glyph_count=档位信息。 */ static int meow_font_probe_family(const char *dirpath, const char *family, - char *label, int llen) + char *label, int llen, + char *charset, int clen, int *glyph_count) { char ppath[400], ipath[400], jpath[400]; snprintf(ppath, sizeof ppath, "%s/font.png", dirpath); @@ -1694,9 +1800,15 @@ static int meow_font_probe_family(const char *dirpath, const char *family, return 0; } char name[64] = "", jsha_png[80] = "", jsha_idx[80] = ""; + char cs[8] = ""; int gc = 0; meow_font_json_probe(jpath, name, sizeof name, jsha_png, sizeof jsha_png, - jsha_idx, sizeof jsha_idx); - snprintf(label, llen, "%s", name[0] ? name : family); /* 显示名:name 或回退目录名 */ + jsha_idx, sizeof jsha_idx, cs, sizeof cs, &gc); + /* 显示名 = 名 + 档位大小标记(如 `default(common≈4k)` / `gbk≈20k` / `full`) */ + char marker[24]; + font_tier_marker(cs, gc, marker, sizeof marker); + snprintf(label, llen, "%s(%s)", name[0] ? name : family, marker); + if (charset) snprintf(charset, clen, "%s", cs[0] ? cs : "common"); + if (glyph_count) *glyph_count = gc; /* 完整性校验:仅 WARN,不硬失败;该套仍标记可选。 */ char apng[80] = "", aidx[80] = ""; if (font_sha256_file(ppath, apng, sizeof apng) != 0) @@ -1707,7 +1819,7 @@ static int meow_font_probe_family(const char *dirpath, const char *family, logmsg("fonts: '%s' sha256(idx) 不可用,跳过校验", family); else if (jsha_idx[0] && !font_sha_eq(aidx, jsha_idx)) logmsg("fonts: '%s' WARN sha256_idx 不匹配(仍可选)", family); - logmsg("fonts: add '%s' (%s)", label, family); + logmsg("fonts: add '%s' (%s) charset=%s glyph_count=%d", label, family, cs[0]?cs:"common", gc); return 1; } @@ -1717,7 +1829,20 @@ static void meow_font_scan_presets_root(const char *card_root) { font_presets_n = 0; font_presets[0] = "MeowOS/fonts/default/font.png"; /* 默认字库 = MeowOS/fonts/default */ - font_preset_labels[0] = "默认字体"; + font_preset_labels[0] = font_preset_label_buf[0]; /* 指向缓冲(运行时派生含大小标记) */ + /* 默认套也读 font.json 档位(存在则跟真实档,缺则 common);档位信息供分层装载/标注。 */ + { + char jp[400], cs[8] = ""; int gc = 0; + char nm0[64] = "", sp0[80] = "", si0[80] = ""; + snprintf(jp, sizeof jp, "%s/%s/default/font.json", card_root, MEOW_FONTS_CFG); + meow_font_json_probe(jp, nm0, sizeof nm0, sp0, sizeof sp0, si0, sizeof si0, + cs, sizeof cs, &gc); + char mk[24]; font_tier_marker(cs, gc, mk, sizeof mk); + snprintf(font_preset_label_buf[0], sizeof font_preset_label_buf[0], "默认字体(%s)", mk); + snprintf(font_preset_tier_buf[0], sizeof font_preset_tier_buf[0], "%s", cs[0]?cs:"common"); + font_preset_tiers[0] = font_preset_tier_buf[0]; + font_preset_glyphs[0] = gc; + } font_presets_n = 1; char root[340]; snprintf(root, sizeof root, "%s/%s", card_root, MEOW_FONTS_CFG); @@ -1726,16 +1851,20 @@ static void meow_font_scan_presets_root(const char *card_root) struct dirent *de; while ((de = readdir(d)) && font_presets_n < FONT_PRESETS_MAX) { if (de->d_name[0] == '.') continue; - char dirpath[400], label[64]; + char dirpath[400], label[80], cs[8] = ""; int gc = 0; snprintf(dirpath, sizeof dirpath, "%s/%s", root, de->d_name); - if (meow_font_probe_family(dirpath, de->d_name, label, sizeof label) == 0) + if (meow_font_probe_family(dirpath, de->d_name, label, sizeof label, + cs, sizeof cs, &gc) == 0) continue; /* 缺组件/损坏 → 跳过该套 */ int i = font_presets_n; snprintf(font_preset_val_buf[i], sizeof font_preset_val_buf[i], "%s/%s/font.png", MEOW_FONTS_CFG, de->d_name); snprintf(font_preset_label_buf[i], sizeof font_preset_label_buf[i], "%s", label); + snprintf(font_preset_tier_buf[i], sizeof font_preset_tier_buf[i], "%s", cs[0]?cs:"common"); font_presets[i] = font_preset_val_buf[i]; font_preset_labels[i] = font_preset_label_buf[i]; + font_preset_tiers[i] = font_preset_tier_buf[i]; + font_preset_glyphs[i] = gc; font_presets_n++; } closedir(d); @@ -2321,17 +2450,14 @@ static void settings_sync_cache_listener(const char *key) else if (!strcmp(key, "power.forceoff_ms")) { int v; if (meow_settings_get_int("power.forceoff_ms", &v) == 0) power_forceoff_ms = v; } } -/* ---- 通知 dump 回调占位(通知#6 转储 TF 卡;接线/占位,不做 TF 写)---- +/* ---- 通知 dump 回调(通知#6 转储 TF 卡;做成真)---- * meow_notif 在 TTL 到点(meow_notif_tick,§8 10s)调用此回调归档一条通知,随后释放槽。 - * 基座只把回调挂上来(见 settings_load 的 meow_notif_set_dump_cb);真实 TF 落盘 - * (按 NOTIFICATION_SYSTEM.md §8 / TF_CARD_LAYOUT.md 写 <卡>/MeowOS/notify/...)由后续 - * 通知代理在回调体内实现。注意 meow_notif.c 的 archive_one 自身已 log 一行 "dump: ...", - * 故本回调保持轻量(避免重复刷屏),落盘逻辑填在下方 TODO 处。 */ + * 本回调把 meow_notif 结构体转成一行 CSV 追加写入 <卡>/MeowOS/notifications/notifications.log + * (含 mkdir -p 与按总大小滚动截断、保留最新 10MB),落盘实现在 meow_notif.c 的 + * meow_notif_dump_tf()。无卡/不可写仅打点降级(NOTIFICATION_SYSTEM.md §5/§8 + MEWSPEC §5.3)。 */ static void notif_dump_tf_placeholder(const meow_notif_t *n) { - (void)n; - /* TODO(通知代理, M2c):在此写 TF 卡 /notify//.json 等; - * 基座不实现,仅保留挂接点(触发时机=meow_notif_tick 内 10s 到点/止机转储)。 */ + meow_notif_dump_tf(n); } /* 启动加载(M2.11/M2.24):统一由 meow_settings 后端读 settings.conf; @@ -2342,7 +2468,7 @@ static void settings_load(void) { meow_settings_init(); /* 幂等:注册默认 + 读 settings.conf */ meow_notif_init(); /* M2a:通知存储初始化(幂等,读 notify.* 配额) */ - meow_notif_set_dump_cb(notif_dump_tf_placeholder); /* 基座(通知#6):挂 dump 回调(TF 转储占位,M2c 落盘由后续代理实现) */ + meow_notif_set_dump_cb(notif_dump_tf_placeholder); /* 通知#6:挂 dump 回调 = TF 转储(meow_notif_dump_tf:一行 CSV 追加 + 10MB 滚动截断) */ if (!settings_cache_registered) { meow_settings_add_listener(settings_sync_cache_listener); settings_cache_registered = 1; @@ -4483,6 +4609,10 @@ static const srow_t SMENU[] = { /* 字体主题 */ { "字体主题", NULL, SC_HEADER, 0,0,0, NULL,NULL,0 }, { "字体文件", "font.file", SC_PRESET, 0,0,0, font_presets, font_preset_labels, 0 }, + /* M2.5x 字体档位分层/按需大字库:「加载大字库」= font.load_full(int 0/1 默认 0)。 + * 开 → 强制全系统用大字库 gbk≈20k 档(覆盖 app 未声明/覆盖默认 font.file); + * 关(默认)→ 小字库 common≈4k,仅 app 声明 fonts:"full" 才大字库。 */ + { "加载大字库", "font.load_full", SC_SWITCH, 0,0,0, NULL,NULL,0 }, /* M2.5x 多字体:开关 + 6 个字符类别字体(preset=可用 MeowOS/fonts// 列表; * 值空 = 跟随全局 font.file)。仅开关开启时 6 行可见(s_row_visible)。 */ { "多字体", "display.multi_font", SC_SWITCH, 0,0,0, NULL,NULL,0 }, @@ -5433,6 +5563,20 @@ static void s_commit(const srow_t *r, int save_now) meow_font_reload_multifont(); /* M2.5x:全局字体变更 → 重配多字体(各类跟随全局者随之更新) */ meow_dirty_full(); /* 字体变化可能影响所有文本渲染,整帧重绘 */ } + /* M2.5x「加载大字库」开关(font.load_full)变更 → 强制重载 launcher 自身字体(小/大字库切换), + * 并重配多字体;大字库 atlas 大,meow_font_ensure 先 unload 旧再 load 新(防双驻留)。 */ + else if (!strcmp(r->key, "font.load_full")) { + mfont_ready = 0; + mfont_forced = 1; /* 跳过 SDK 复用捷径,强制按生效档(gbk/common)真实 reload */ + if (!meow_font_ensure()) + logmsg("font.load_full: reload failed -> dotmatrix fallback"); + else { + int lf = 0; meow_settings_get_bool("font.load_full", &lf); + logmsg("font.load_full: reloaded (load_full=%d)", lf); + } + meow_font_reload_multifont(); + meow_dirty_full(); + } /* M2.5x 多字体:开关或任一类别字体变更 → 重新去重装载类别字库并重绘(多字体可能影响文本渲染)。 */ else if (!strcmp(r->key, "display.multi_font") || !strncmp(r->key, "font.class_", 11)) { meow_font_reload_multifont(); @@ -6846,12 +6990,14 @@ static int launch_app(struct app *a) meow_settings_get_bool("display.multi_font", &mf_on); snprintf(env_mf, sizeof env_mf, "MEOW_MULTI_FONT=%d", mf_on ? 1 : 0); envp[ne++] = env_mf; - /* M2.x(基座):字库档 MEOW_FONT_TIER=<0|1|2> —— 按 app.json "fonts" 声明注入; - * 0=默认4K常用(未声明/缺省),1=大字库GBK,2=Full。SDK meow_ui_gfx 读入存档, - * 真正按档装载大字库由后续 font 代理实现(见 meow_font_effective_paths_tiered)。 */ - snprintf(env_tier, sizeof env_tier, "MEOW_FONT_TIER=%d", a->fonts); + /* M2.5x:字库档 MEOW_FONT_TIER=<0|1|2> —— 按 app.json "fonts" 声明注入,并合并 + * 「加载大字库」开关(font.load_full → 强制 ≥GBK)得**生效档**;0=默认4K常用, + * 1=大字库GBK,2=Full。SDK meow_ui_gfx 读入存档并按档装载(见 + * meow_font_effective_paths_tiered;真正装载由 meow_font_reload_tier 实现)。 */ + int eff_tier = meow_font_effective_tier(a->fonts); + snprintf(env_tier, sizeof env_tier, "MEOW_FONT_TIER=%d", eff_tier); envp[ne++] = env_tier; - have_global = (meow_font_effective_paths_tiered(a->fonts, fpng, sizeof fpng, + have_global = (meow_font_effective_paths_tiered(eff_tier, fpng, sizeof fpng, fidx, sizeof fidx, fam, sizeof fam) == 0); if (have_global) { snprintf(env_fpng, sizeof env_fpng, "MEOW_FONT_PNG=%s", fpng); diff --git a/patch_v2/meow_launcherd/meow_notif.c b/patch_v2/meow_launcherd/meow_notif.c index f9a5c55..907ee95 100644 --- a/patch_v2/meow_launcherd/meow_notif.c +++ b/patch_v2/meow_launcherd/meow_notif.c @@ -24,6 +24,11 @@ #include /* strcasecmp */ #include #include +#include /* mkdir / stat */ +#include +#include /* open/close/write/pread/lseek/ftruncate */ +#include /* O_* */ +#include /* errno/strerror */ #include "meow_notif.h" #include "meow_settings.h" /* B2a:读 notify.* 配额(MEOW_OK/MEOW_ERR_*) */ @@ -89,6 +94,192 @@ static void n_strncpy(char *dst, const char *src, size_t len) dst[len - 1] = 0; } +/* ================= TF 卡转储(通知#6 / M2c,NOTIFICATION_SYSTEM.md §5/§8)================= + * 每条通知一行 CSV 追加到 <卡根>/MeowOS/notifications/notifications.log,并按日志总大小 + * 滚动截断(保留最新 10MB)。系统文件统一放 <卡根>/MeowOS/ 下(TF_CARD_LAYOUT.md)。 */ +#define MEOW_NOTIF_TF_DIR "/usr/data/mnt/sd_0/MeowOS/notifications" +#define MEOW_NOTIF_TF_LOG MEOW_NOTIF_TF_DIR "/notifications.log" +#define MEOW_NOTIF_LOG_MAX_BYTES ((size_t)10 * 1024 * 1024) /* §8:保留最新 10MB */ + +/* 单行 CSV 上限:app_id(32)/category(24)/summary(64)/body(96)/target_activity(48) + * 全引号转义后仍远小于此。 */ +#define MEOW_NOTIF_CSV_LINE_MAX 1024 + +static const char *g_tf_path = MEOW_NOTIF_TF_LOG; +static size_t g_tf_max = MEOW_NOTIF_LOG_MAX_BYTES; + +/* 递归 mkdir -p:沿 path 把每一级目录建出来(EEXIST 无害;无卡/只读则静默失败) */ +static void tf_mkdirs(const char *path) +{ + char tmp[512]; + n_strncpy(tmp, path, sizeof tmp); + for (char *p = tmp + 1; *p; p++) { + if (*p == '/') { + *p = '\0'; + mkdir(tmp, 0755); + *p = '/'; + } + } +} + +/* 全量写入(处理短写/EINTR) */ +static int tf_write_all(int fd, const char *buf, size_t len) +{ + size_t off = 0; + while (off < len) { + ssize_t w = write(fd, buf + off, len - off); + if (w < 0) { + if (errno == EINTR) continue; + return -1; + } + off += (size_t)w; + } + return 0; +} + +/* CSV 字段:去换行(\r\n->空格,保证单行)+ 转义(双引号包裹,内部 " 翻倍) */ +static void csv_field(char *dst, size_t dstsz, const char *src) +{ + if (!dst || dstsz == 0) return; + size_t o = 0; + dst[o++] = '"'; + for (const char *p = src ? src : ""; *p; p++) { + if (o + 4 > dstsz) break; /* 留 2 字节给翻倍引号 + 收尾引号 + NUL */ + if (*p == '\r' || *p == '\n') dst[o++] = ' '; /* 去换行 */ + else if (*p == '"') { dst[o++] = '"'; dst[o++] = '"'; } + else dst[o++] = *p; + } + if (o + 1 >= dstsz) o = dstsz - 1; + dst[o++] = '"'; + dst[o] = '\0'; +} + +/* 生成一行 CSV: + * timestamp,id,app_id,category,urgency,title,body,target_activity,ongoing,media,dismissed + * title<-summary;urgency:meow_notif 结构无该字段(保持既有 API),列值留空 ""。 + * 返回写入长度(不含 NUL)。 */ +static size_t tf_line(const meow_notif_t *n, char *buf, size_t bufsz) +{ + char a_app [2 + 2 * MEOW_NOTIF_APP_ID_MAX + 2]; + char a_cat [2 + 2 * MEOW_NOTIF_CAT_MAX + 2]; + char a_sum [2 + 2 * MEOW_NOTIF_SUMMARY_MAX + 2]; + char a_body[2 + 2 * MEOW_NOTIF_BODY_MAX + 2]; + char a_tgt [2 + 2 * MEOW_NOTIF_ACTIVITY_MAX + 2]; + csv_field(a_app, sizeof a_app, n->app_id); + csv_field(a_cat, sizeof a_cat, n->category); + csv_field(a_sum, sizeof a_sum, n->summary); + csv_field(a_body, sizeof a_body, n->body); + csv_field(a_tgt, sizeof a_tgt, n->target_activity); + int r = snprintf(buf, bufsz, + "%llu,%u,%s,%s,\"\",%s,%s,%s,%u,%u,%u\n", + (unsigned long long)n->created_ms, + (unsigned)n->id, + a_app, a_cat, a_sum, a_body, a_tgt, + n->ongoing ? 1u : 0u, + n->media ? 1u : 0u, + n->dismissed ? 1u : 0u); + if (r < 0) return 0; + return ((size_t)r < bufsz) ? (size_t)r : bufsz - 1; +} + +/* 滚动截断:文件超过 g_tf_max 时删除最旧行(从尾部读窗口定位第一条换行作为保留起点), + * 把结尾 ≤max 字节的完整行重写回文件头。窗口内无换行则保留整窗(只保证 ≤max)。 */ +static int tf_trim(const char *path) +{ + int fd = open(path, O_RDWR); + if (fd < 0) return -1; + struct stat st; + if (fstat(fd, &st) != 0) { close(fd); return -1; } + off_t size = st.st_size; + if (size <= (off_t)g_tf_max) { close(fd); return 0; } + + off_t start = size - (off_t)g_tf_max; /* 保留窗口起点 */ + off_t keep = start; /* 最终保留起点(行对齐后) */ + int found = 0; + char chunk[8192]; + for (off_t pos = start; pos < size && !found; ) { + size_t want = (size_t)((size - pos) < (off_t)sizeof chunk ? (size - pos) : (off_t)sizeof chunk); + ssize_t rd = pread(fd, chunk, want, pos); + if (rd <= 0) break; + for (ssize_t i = 0; i < rd; i++) { + if (chunk[i] == '\n') { keep = pos + i + 1; found = 1; break; } + } + pos += rd; + if (rd < (ssize_t)want) break; /* 读到文件尾 */ + } + + /* 重写:把 [keep, size) 拷贝回文件头,再 ftruncate 掉尾部旧数据 */ + off_t remain = size - keep; + if (lseek(fd, 0, SEEK_SET) < 0) { close(fd); return -1; } + off_t wpos = 0; + char buf[8192]; + while (remain > 0) { + size_t want = (size_t)(remain < (off_t)sizeof buf ? remain : (off_t)sizeof buf); + ssize_t rd = pread(fd, buf, want, keep + wpos); + if (rd <= 0) break; + if (tf_write_all(fd, buf, (size_t)rd) < 0) { close(fd); return -1; } + wpos += rd; + remain -= rd; + } + ftruncate(fd, wpos); + close(fd); + return 0; +} + +/* 把一条通知追加为一行 CSV 到 TF 日志(含 mkdir -p 与 10MB 滚动截断)。 + * 返回 NOTIF_OK(0);无卡/不可写/参数非法返回负(降级:仅打点,不崩)。 */ +int meow_notif_dump_tf(const meow_notif_t *n) +{ + if (!n) return NOTIF_ERR_INVAL; + if (!g_tf_path || !g_tf_path[0]) return NOTIF_ERR_INVAL; + tf_mkdirs(g_tf_path); /* 目录不存在则 mkdir -p*/ + + char line[MEOW_NOTIF_CSV_LINE_MAX]; + size_t len = tf_line(n, line, sizeof line); + if (len == 0) return NOTIF_ERR_INVAL; + + int fd = open(g_tf_path, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd < 0) { + notif_log("tf: append open fail %s (%s)", g_tf_path, strerror(errno)); + return NOTIF_ERR_IO; + } + if (tf_write_all(fd, line, len) != 0) { + close(fd); + notif_log("tf: append write fail %s (%s)", g_tf_path, strerror(errno)); + return NOTIF_ERR_IO; + } + long size = -1; + struct stat st; + if (fstat(fd, &st) == 0) size = (long)st.st_size; + close(fd); + + if (size > (long)g_tf_max) { /* >10MB:滚动截断,保留最新 */ + tf_trim(g_tf_path); + notif_log("tf: rolled to <= %zuB", g_tf_max); + } + return NOTIF_OK; +} + +/* 开机清板载通知:清空转储日志文件,保留目录(通知#6 / §8:启动时清板载) */ +void meow_notif_clear_tf(void) +{ + if (!g_tf_path || !g_tf_path[0]) return; + tf_mkdirs(g_tf_path); + int fd = open(g_tf_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd >= 0) close(fd); + else notif_log("tf: clear fail %s (%s)", g_tf_path, strerror(errno)); +} + +/* 覆盖转储日志路径/滚动上限(宿主单测用;NULL/0 恢复默认) */ +void meow_notif_set_tf_path(const char *path) +{ + g_tf_path = (path && path[0]) ? path : MEOW_NOTIF_TF_LOG; +} +void meow_notif_set_tf_max(size_t max_bytes) +{ + g_tf_max = max_bytes ? max_bytes : MEOW_NOTIF_LOG_MAX_BYTES; +} + /* ---- 配额读取(B2a;键缺省/取失败用默认值)---- */ static void read_quota(void) { @@ -113,7 +304,11 @@ int meow_notif_init(void) g_dumped_total = 0; read_quota(); /* B2a:notify.* 配额 */ g_inited = 1; - notif_log("init: slots=%d default dump_cb=log-only (M2c -> TF)", MEOW_NOTIF_MAX_SLOTS); + /* 通知#6:启动清板载通知 + 内存表(内存表上面已 memset;这里清 TF 转储日志, + * 保留目录)。每会话从零开始(通知会话级),不被电源事件清(before_poweroff 只管内存)。 */ + meow_notif_clear_tf(); + notif_log("init: slots=%d tf_log=%s (dump_cb wired by launcher -> meow_notif_dump_tf)", + MEOW_NOTIF_MAX_SLOTS, g_tf_path); return NOTIF_OK; } diff --git a/patch_v2/meow_launcherd/meow_notif.h b/patch_v2/meow_launcherd/meow_notif.h index 35c8183..7791816 100644 --- a/patch_v2/meow_launcherd/meow_notif.h +++ b/patch_v2/meow_launcherd/meow_notif.h @@ -32,7 +32,8 @@ enum { NOTIF_ERR_NOMEM = -6, /* 槽满/内存不足 */ NOTIF_ERR_NOTINIT = -7, /* 未 init */ NOTIF_ERR_QUOTA = -12, /* 配额超限(App 类型数 / 类型条数 / 媒体数) */ - NOTIF_ERR_NOENT = -2 /* 通知 id 不存在 */ + NOTIF_ERR_NOENT = -2, /* 通知 id 不存在 */ + NOTIF_ERR_IO = -5 /* 文件/存储 IO 失败(TF 转储,无卡/不可写) */ }; /* == 容量/长度(单设备上限;定长,控制静态内存)== */ @@ -118,6 +119,17 @@ void meow_notif_before_poweroff(void); /* 覆盖转储回调(NULL=恢复默认日志;M2c 接 TF 落盘)。 */ void meow_notif_set_dump_cb(meow_notif_dump_cb cb); +/* == TF 卡转储(通知#6 / M2c,NOTIFICATION_SYSTEM.md §5/§8 + MEOWOS_SPEC_REF §5.3)== + * 把 dump_cb 接到 meow_notif_dump_tf 即把每条通知追加为一行 CSV 到 + * <卡根>/MeowOS/notifications/notifications.log,并按日志总大小滚动截断 + * (保留最新 10MB,不被电源事件清;启动时 meow_notif_init 先清板载+内存表)。 + * 字段按 meow_notif 结构(title<-summary;urgency 结构无字段故列留空;均做 CSV + * 转义/去换行)。无卡/不可写仅打点降级,绝不崩。 */ +int meow_notif_dump_tf(const meow_notif_t *n); /* 0=成功;负=失败(无卡/IO/参数) */ +void meow_notif_clear_tf(void); /* 开机清板载通知(清空文件,保留目录) */ +void meow_notif_set_tf_path(const char *path); /* 覆盖转储日志路径;NULL=恢复默认卡路径(宿主单测用) */ +void meow_notif_set_tf_max(size_t max_bytes); /* 覆盖滚动截断上限;0=恢复默认 10MB(宿主单测用) */ + /* 调试:打印当前 Active 表/App 表(前缀)。 */ void meow_notif_dump(const char *log_prefix); diff --git a/patch_v2/meow_launcherd/meow_settings.c b/patch_v2/meow_launcherd/meow_settings.c index e941887..67bace2 100644 --- a/patch_v2/meow_launcherd/meow_settings.c +++ b/patch_v2/meow_launcherd/meow_settings.c @@ -104,6 +104,10 @@ static const meow_setting_def g_defs[] = { { "font.class_latin", SET_STR, "", 0,0, NULL, NULL }, { "font.class_latin_sym", SET_STR, "", 0,0, NULL, NULL }, { "font.class_other", SET_STR, "", 0,0, NULL, NULL }, + /* M2.5x 字体档位分层 / 按需大字库:font.load_full(int 0/1 默认 0)=「加载大字库」开关, + * 1=强制全系统用大字库 gbk≈20k 档(覆盖 app 未声明/覆盖默认 font.file); + * 0=默认小字库 common≈4k,仅 app 声明 fonts:"full" 才大字库。见 §5.2/§5.7.8。 */ + { "font.load_full", SET_INT, "0", 0, 1, NULL, NULL }, { "font.size.title", SET_INT, "28", 0, 0, NULL, NULL }, { "font.size.body", SET_INT, "20", 0, 0, NULL, NULL }, { "ui.style", SET_ENUM, "md3", 0, 0, "md3,miui", "Material You,MIUI" }, diff --git a/patch_v2/meow_launcherd/test_notif_tf.c b/patch_v2/meow_launcherd/test_notif_tf.c new file mode 100644 index 0000000..97a9cbb --- /dev/null +++ b/patch_v2/meow_launcherd/test_notif_tf.c @@ -0,0 +1,158 @@ +/* test_notif_tf.c — 宿主单测:通知#6 TF 转储(CSV 转义 / 10MB 滚动截断 / init 清板载+内存表)。 + * + * 直接 #include "meow_notif.c"(同 TU 平移其 static 常量/函数),stub 掉 meow_settings_get_int + * (配额读——返回负=键缺失即用默认,涵盖 CSV/截断/init 逻辑)。宿主 gcc 编译运行即可,不进固件。 + * + * 运行:gcc -D_GNU_SOURCE -o test_notif_tf test_notif_tf.c && ./test_notif_tf + */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +/* stub:meow_notif.c 的 read_quota() 读 notify.* 配额。<0 => 键缺失=> 用默认值 */ +int meow_settings_get_int(const char *key, int *out) +{ + (void)key; (void)out; + return -2; /* MEOW_ERR_NOENT */ +} + +#include "meow_notif.c" /* 把全部实现(含 statics)收进本 TU */ + +static int g_fail = 0; +#define CHECK(cond, msg) do { \ + if (!(cond)) { fprintf(stderr, "FAIL: %s (%s:%d)\n", msg, __FILE__, __LINE__); g_fail++; } \ + else fprintf(stderr, "ok: %s\n", msg); \ +} while (0) + +static char *read_all(const char *path, long *out_len) +{ + FILE *f = fopen(path, "rb"); + if (!f) return NULL; + fseek(f, 0, SEEK_END); + long n = ftell(f); + fseek(f, 0, SEEK_SET); + char *s = malloc((size_t)n + 1); + if (!s) { fclose(f); return NULL; } + size_t got = fread(s, 1, (size_t)n, f); + s[got] = 0; + fclose(f); + if (out_len) *out_len = n; + return s; +} + +static void make_notif(meow_notif_t *n, uint32_t id, const char *sum, const char *body) +{ + memset(n, 0, sizeof *n); + n->id = id; + n->created_ms = 1234567890123ULL; + strcpy(n->app_id, "com.app"); + strcpy(n->category, "general"); + strcpy(n->summary, sum); + strcpy(n->body, body); + strcpy(n->target_activity, "act"); + n->ongoing = 1; +} + +/* --- 1) CSV 转义 + 去换行 --- */ +static void test_csv_escape(const char *path) +{ + meow_notif_set_tf_path(path); + meow_notif_set_tf_max(1024 * 1024); /* 放大上限避免此测触发截断 */ + + meow_notif_t n; + /* summary: 逗号 + 双引号 + 换行;body: CRLF + tab */ + make_notif(&n, 42, "Hel\"lo, world\nline2", "Body\r\nwith\ttab"); + n.media = 1; /* 让 media 列=1 */ + CHECK(meow_notif_dump_tf(&n) == 0, "dump_tf returns 0"); + + char *s = read_all(path, NULL); + CHECK(s != NULL, "file exists after dump"); + const char *expect = + "1234567890123,42,\"com.app\",\"general\",\"\",\"Hel\"\"lo, world line2\"," + "\"Body with\ttab\",\"act\",1,1,0\n"; /* ongoing=1 media=1 dismissed=0 */ + CHECK(s && strcmp(s, expect) == 0, "CSV line matches expected (escape+newline-strip)"); + if (s) { fprintf(stderr, " got: %s", s); fprintf(stderr, " exp: %s", expect); } + free(s); +} + +/* --- 2) 10MB 滚动截断(假文件:把上限压到很小模拟)--- */ +static void test_trim(const char *path) +{ + meow_notif_set_tf_path(path); + meow_notif_set_tf_max(256); /* 用 256B 模拟 10MB 上限 */ + + /* 先写 4 条不同标记,让文件超过 256B */ + meow_notif_t n; + make_notif(&n, 1, "lineAAAA", ""); + meow_notif_dump_tf(&n); + make_notif(&n, 2, "lineBBBB", ""); + meow_notif_dump_tf(&n); + make_notif(&n, 3, "lineCCCC", ""); + meow_notif_dump_tf(&n); + make_notif(&n, 4, "lineDDDD", ""); + meow_notif_dump_tf(&n); + + long len = 0; + char *s = read_all(path, &len); + CHECK(s != NULL && len <= 256, "after roll, file size <= limit (10MB analog)"); + CHECK(s && strstr(s, "lineDDDD") != NULL, "newest row retained after roll"); + CHECK(s && strstr(s, "lineAAAA") == NULL, "oldest row rolled away"); + if (s) fprintf(stderr, " rolled content (%ldB):\n%s", len, s); + + /* 追加一条仍 0 成功 */ + make_notif(&n, 5, "lineEEEE", ""); + CHECK(meow_notif_dump_tf(&n) == 0, "append after roll ok"); + free(s); +} + +/* --- 3) init 清板载 + 清内存表,且 post 正常 --- */ +static void test_init_clear(const char *path) +{ + meow_notif_set_tf_path(path); + meow_notif_set_tf_max(1024 * 1024); + + /* 先塞点板载内容 */ + meow_notif_t n; + make_notif(&n, 99, "junk", ""); + meow_notif_dump_tf(&n); + + /* init:应清板载文件 + 清内存表 */ + CHECK(meow_notif_init() == NOTIF_OK, "meow_notif_init ok"); + long len = -1; + char *s = read_all(path, &len); + CHECK(s != NULL && len == 0, "board log cleared at init (dir kept)"); + CHECK(meow_notif_count(NULL) == 0, "memory table cleared at init"); + + /* init 后 post 一条,应活跃 + 可转储 */ + make_notif(&n, 0, "fresh", ""); + uint32_t id = 0; + CHECK(meow_notif_post(&n, &id) == NOTIF_OK, "post after init ok"); + CHECK(id != 0 && meow_notif_count(NULL) == 1, "one active notif after post"); + free(s); +} + +int main(void) +{ + char tmp[] = "/tmp/meow_notif_tf_test_XXXXXX"; + char *dir = mkdtemp(tmp); + if (!dir) { perror("mkdtemp"); return 2; } + + char p1[512], p2[512], p3[512]; + snprintf(p1, sizeof p1, "%s/csv.log", dir); + snprintf(p2, sizeof p2, "%s/trim.log", dir); + snprintf(p3, sizeof p3, "%s/init.log", dir); + + CHECK(p1[0] != 0, "tmpdir ready"); + test_csv_escape(p1); + test_trim(p2); + test_init_clear(p3); + + /* 清理:删除日志文件 + 目录(保底) */ + unlink(p1); unlink(p2); unlink(p3); rmdir(dir); + + fprintf(stderr, "\n%s (failures=%d)\n", g_fail ? "== TEST FAILED ==" : "== TEST PASSED ==", g_fail); + return g_fail ? 1 : 0; +} diff --git a/patch_v2/sdk/meow_ui.h b/patch_v2/sdk/meow_ui.h index bc17e86..298e379 100644 --- a/patch_v2/sdk/meow_ui.h +++ b/patch_v2/sdk/meow_ui.h @@ -328,22 +328,24 @@ const char *meow_notify_urgency_str(meow_notify_urgency u); const char *meow_notify_category_str(meow_notify_category cat); /* ============================================================ */ -/* §10 字体分层 / 大字库(草案/待定案 —— 本批仅加声明/枚举/宏,不实现) */ +/* §10 字体分层 / 大字库(M2.5x:基座声明 + font 域已实现按档装载) */ /* ============================================================ */ /* 字体「档位」概念:launcher 按 app.json 声明的字库档("fonts":<档>)向 app 注入 - * MEOW_FONT_TIER=<0|1|2>;SDK(meow_ui_gfx / 后续 meow_font 大字库加载)据档选库: + * 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 域代理据此在 meow_font.c / gen_font.py 实现大字库生成与按档装载。 - * 既有 meow_font_* 符号(class_of/has_glyph/load_slot/config_multifont…)保留不动; - * 大字库装载以 set_tier/tier 作为入口,或由后续代理按 meow_font_config_multifont 扩展。 */ + * 大字库生成由 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 定义(只存档 + 触发重载请求);真正按档装载大字库由后续 font 代理实现。 */ + * 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); diff --git a/patch_v2/sdk/meow_ui_gfx.c b/patch_v2/sdk/meow_ui_gfx.c index c429599..d6a9798 100644 --- a/patch_v2/sdk/meow_ui_gfx.c +++ b/patch_v2/sdk/meow_ui_gfx.c @@ -77,8 +77,8 @@ static unsigned long long g_sbar_collapse_start_ms = 0; /* 本次过渡起始 /* ---- 字体档位(MEOW_FONT_TIER,基座存档 + 公共 get/set)---- * launcher 按 app.json "fonts":<档> 注入 MEOW_FONT_TIER=<0|1|2>;SDK 读入并以 - * meow_font_set_tier/tier 暴露。真正按档装载大字库(GBK/Full)由后续 font 代理在 - * meow_font.c / meow_gfx_load_multifont 挂钩实现——此处仅记录档位不换库。 */ + * meow_font_set_tier/tier 暴露。按档装载大字库(GBK/Full)由 meow_font_reload_tier() + * 在 meow_font.c 实现;meow_font_set_tier() 在档位变化时经 env/settings 路由到该钩子真重载。 */ static int g_font_tier = MEOW_FONT_TIER_COMMON; /* ---- 帧率调度(A-1/A-2:从 launcher M2.16 迁入,刷新率调度归口 SDK)---- @@ -665,20 +665,32 @@ unsigned long long meow_ui_frames_presented(void) { return g_frames_presented; } int meow_gfx_is_device(void) { return g_fb_mem != NULL; } int meow_gfx_mfont_ready(void) { return g_mfont_ready; } -/* ---- 字体档位(公共 API,基座定义)---- - * 注意:meow_font_tier()/meow_font_set_tier() 已在 meow_ui_gfx.c 定义(符号唯一), - * 后续 font 代理勿在 meow_font.c 重复定义;可在 meow_font.c 实现「按档装载大字库」并在 - * meow_font_set_tier 的钩子处唤起(见下)。 */ +/* ---- 字体档位(公共 API,基座定义 + font 域真重载钩子)---- + * meow_font_tier()/meow_font_set_tier() 在 meow_ui_gfx.c 定义(符号唯一),font 代理勿在 + * meow_font.c 重复定义;大字库按档装载由 meow_font.c meow_font_reload_tier() 实现,并在 + * meow_font_set_tier() 处唤起(见下)。 */ int meow_font_tier(void) { return g_font_tier; } int meow_font_set_tier(int tier) { + int old = g_font_tier; if (tier < MEOW_FONT_TIER_COMMON) tier = MEOW_FONT_TIER_COMMON; if (tier > MEOW_FONT_TIER_FULL) tier = MEOW_FONT_TIER_FULL; if (tier == g_font_tier) return g_font_tier; g_font_tier = tier; - /* TBD(基座):真正按档装载大字库(meow_font_load_tier 或 config_multifont 扩展)由 - * 后续 font 代理在 meow_font.c 实现;此处仅记录档位 + 标记重载(下一轮 load 读 tier)。 */ + /* 真重载(font 域钩子,M2.5x):按档装载大字库。launcher 已按档解析并注入 + * MEOW_FONT_PNG/IDX(tier>0 → GBK/Full 大字库绝对路径);重读 env 重载。 + * 无 env/失败 → 回退卡默认 MeowOS/fonts/default → 固件。 + * 大字库 atlas 大(GBK≈5-15MB+),meow_font_reload_tier 先 unload 旧再 load 新,防双驻留。 */ + const char *ep = getenv("MEOW_FONT_PNG"); + const char *ei = getenv("MEOW_FONT_IDX"); + if (ep && ep[0] && ei && ei[0] && meow_font_reload_tier(tier, ep, ei) == 0) + return g_font_tier; + if (meow_font_reload_tier(tier, MEOW_FONT_PNG_CARD, MEOW_FONT_IDX_CARD) == 0) + return g_font_tier; + if (meow_font_reload_tier(tier, MEOW_FONT_PNG_SYS, MEOW_FONT_IDX_SYS) == 0) + return g_font_tier; + g_font_tier = old; /* 全部失败 → 回退旧档(字库可能已不可用,5x7 点阵兜底,系统不死) */ return g_font_tier; } @@ -692,9 +704,9 @@ int meow_font_set_tier(int tier) static int load_font(void) { /* 字体档位(MEOW_FONT_TIER env,由 launcher 按 app.json "fonts" 注入): - * 0=默认4K常用 1=大字库GBK 2=Full。基座只读入存档 + 对齐公共 get/set; - * 真正按档装载大字库(GBK/Full 的字库路径/面)由后续 font 代理在 meow_font.c / - * meow_gfx_load_multifont 挂钩实现——此处仍先装载默认(tier0)字库,档位仅记录。 */ + * 0=默认4K常用 1=大字库GBK 2=Full。launcher 已按档解析大字库路径并经 MEOW_FONT_PNG/IDX + * 注入(见 meow_font_effective_paths_tiered),故下方 meow_font_load(ep,ei) 即装载 + * 对应档位字库(tier>0 → GBK/Full 大字库);此处 read env 存档对齐公共 get/set。 */ const char *etr = getenv("MEOW_FONT_TIER"); if (etr && etr[0]) { g_font_tier = atoi(etr); diff --git a/patch_v2/sdk/meow_ui_input.c b/patch_v2/sdk/meow_ui_input.c index fed0fc6..7a155d2 100644 --- a/patch_v2/sdk/meow_ui_input.c +++ b/patch_v2/sdk/meow_ui_input.c @@ -38,6 +38,20 @@ #define QUEUE_N 128 #define MAX_DEVS 8 +/* ── 内部事件:系统级「下拉展开通知中心」(M2.5x 接线)── + * 触摸状态机在抬手判定处识别「SWIPE_DOWN 起始于顶部热区」后压入;事件循环按系统手势处理 + * (路由 meow_ui_sys_notif_pull),不下发给 APP 的 on_swipe(顶部热区为系统保留手势)。 + * 与左缘返回(SWIPE_LEFT)/ meow_ui_swipe_hint 互不影响——后者仍全屏生效,详见下方触摸机。 */ +#define MEOW_EV_NOTIF_PULL 5 + +/* 顶部下滑 → 通知中心判定:纵向 DOWN 手势的起点(origin_y)是否落在顶部热区内。 + * 热区由 meow_ui_statusbar_hotzone() 给出(非全屏=状态栏高、全屏=MEOW_SBAR_HOTZONE_FS、 + * 收合=提示线高)。供宿主单测直调(判据与触摸状态机共用)。 */ +int meow_ui_input_is_notif_pull(int origin_y, int hotzone) +{ + return origin_y >= 0 && origin_y < hotzone; +} + static int g_thread_started = 0; static pthread_t g_thread; static volatile int g_thread_run = 1; @@ -165,7 +179,14 @@ static void touch_release(void) } } else { int dir = mdy > 0 ? MEOW_SWIPE_DOWN : MEOW_SWIPE_UP; - push_ev(MEOW_EV_SWIPE, dir, ady > adx ? ady : adx); + /* 顶部下滑 → 通知中心(系统手势,不下发 APP):起点在顶部热区内才认。 + * 热区高度随状态变化(非全屏=整条状态栏、全屏=MEOW_SBAR_HOTZONE_FS 缩小、 + * 收合=提示线高)——全屏 app 只在顶部极窄热区被系统占用,故「不影响全屏 app」。 */ + if (dir == MEOW_SWIPE_DOWN && + meow_ui_input_is_notif_pull(t_dy, meow_ui_statusbar_hotzone())) + push_ev(MEOW_EV_NOTIF_PULL, t_dy, ady > adx ? ady : adx); + else + push_ev(MEOW_EV_SWIPE, dir, ady > adx ? ady : adx); } } else { push_ev(MEOW_EV_TAP, t_cx, t_cy); @@ -287,6 +308,11 @@ void meow_ui_run(const meow_ui_events *ev) } else if (e.a == MEOW_SWIPE_LEFT && sb_active) { meow_ui_request_exit(); } + } else if (e.type == MEOW_EV_NOTIF_PULL) { + if (in_startup) continue; /* 启动窗口顶区误触残留:丢弃,防进入即开通知中心 */ + /* 系统级「下拉展开通知中心」:起始于顶部热区的下滑为系统保留手势,不下发 + * APP on_swipe;路由到系统钩子(当前为记录占位,通知中心 UI 为后续里程碑)。 */ + meow_ui_sys_notif_pull(); } else if (e.type == MEOW_EV_SWIPE_PROGRESS) { if (in_startup) continue; /* 启动窗口进度条静音 */ int x0 = e.a, xc = e.b, dx = xc - x0; /* dx=当前X-按下X */ diff --git a/patch_v2/sdk/meow_ui_sys.c b/patch_v2/sdk/meow_ui_sys.c index c271f5e..e21900e 100644 --- a/patch_v2/sdk/meow_ui_sys.c +++ b/patch_v2/sdk/meow_ui_sys.c @@ -156,18 +156,31 @@ void meow_ui_set_fullscreen(int on) int meow_ui_statusbar_height(void) { - return meow_ui_sys_statusbar_active() ? MUI_SBAR_H : 0; + if (!meow_ui_sys_statusbar_active()) return 0; + return meow_ui_statusbar_collapsed() ? MUI_SBAR_COLLAPSE_H : MUI_SBAR_H; } /* ---- 内部(gfx/input 用) ---- */ int meow_ui_sys_statusbar_active(void) { - return g_statusbar_on && !g_fullscreen; + /* collapsed 视为状态栏仍激活(只留提示线):与 fullscreen 并存(全屏启 collapsed)—— + * 这样 gfx.c present() 的收合动画块会运行(驱动 g_sbar_collapse_h 插值),且顶部提示线 + * 正常绘制/热区可用。fullscreen 且不 collapsed → 整条隐藏(沉浸,inset=0),保持既有语义。 */ + return g_statusbar_on && (meow_ui_statusbar_collapsed() || !g_fullscreen); } int meow_ui_sys_statusbar_height(void) { - return meow_ui_sys_statusbar_active() ? MUI_SBAR_H : 0; + if (!meow_ui_sys_statusbar_active()) return 0; + return meow_ui_statusbar_collapsed() ? MUI_SBAR_COLLAPSE_H : MUI_SBAR_H; +} + +void meow_ui_sys_notif_pull(void) +{ + /* 系统级「下拉展开通知中心」手势接线(M2.5x):输入层识别出「起始于顶部热区的 + * SWIPE_DOWN」后路由到此。通知中心 UI 为后续里程碑——此处先落记录(避免哑无痕); + * 届时由对应代理在该入口挂真实展开逻辑(IPC SHOW_ACTIVITY / 覆盖层渲染)。 */ + meow_log(MEOW_LOG_WARN, "notif_pull: notification center TBD (wired)"); } int meow_ui_sys_statusbar_force(void) diff --git a/patch_v2/sdk/meow_ui_sys.h b/patch_v2/sdk/meow_ui_sys.h index 8caeb68..de80a7d 100644 --- a/patch_v2/sdk/meow_ui_sys.h +++ b/patch_v2/sdk/meow_ui_sys.h @@ -34,6 +34,13 @@ typedef struct meow_sys_state { #define MUI_SBAR_H 28 #define MUI_SBAR_FONT 20 +/* 收合(collapsed)状态下状态栏的有效加载高度(inset)= 顶部提示线高度(px)。 + * 收合=状态栏内容上移出屏、只留一条提示线:app 内容据此上移(非满 28), + * 形成「不完全沉浸(留提示线)」;与 fullscreen(整条隐藏、inset0)区别。 + * 取值沿用公共宏 MEOW_SBAR_HOTZONE_FS(=4,全屏时顶部热区/提示线的缩后高度), + * 具体绘制高度(gfx.c 的 MUI_SBAR_HINT_H=6)在渲染端,这里按提示线高度口径即可。 */ +#define MUI_SBAR_COLLAPSE_H MEOW_SBAR_HOTZONE_FS + /* 首次全量读取;失败仍返回 0(字段置 -1/0)。 */ int meow_ui_sys_init(void); @@ -43,12 +50,21 @@ void meow_ui_sys_refresh(void); /* 当前快照(内部只读)。 */ const meow_sys_state *meow_ui_sys_get(void); -/* 状态栏是否应绘制(= set_statusbar(1) 且 非 fullscreen)。 */ +/* 状态栏是否应绘制(= set_statusbar(1) 且 非 fullscreen),收合(collapsed)兼容: + * collapsed 视为状态栏仍在(只留提示线),故 collapsed 时即使 fullscreen 也返回 1, + * 让渲染端/输入层继续驱动上收动画与提示线;fullscreen 且不 collapsed → 0(整条隐藏, + * 沉浸,保持既有语义)。 */ int meow_ui_sys_statusbar_active(void); -/* 状态栏高度(px):active 时 28,否则 0(供 meow_ui_statusbar_height 用)。 */ +/* 状态栏有效高度(px,供 inset/提示条定位):active 时 28;collapsed 时=提示线高度 + * MUI_SBAR_COLLAPSE_H(非满 28,app 内容可上移);否则 0(供 meow_ui_statusbar_height 用)。 */ int meow_ui_sys_statusbar_height(void); +/* 系统级「下拉展开通知中心」手势挂钩(M2.5x 接线):输入层识别出「起始于顶部热区的 + * SWIPE_DOWN」后路由到这里。通知中心 UI 为后续里程碑,此入口作记录/占位;届时由对应 + * 代理在此挂真实展开逻辑(IPC SHOW_ACTIVITY / 覆盖层渲染)。 */ +void meow_ui_sys_notif_pull(void); + /* 自上次渲染后状态栏数据是否已变(1s 轻刷/显隐切换置位);读取即清除。 * 渲染后端 present() 用它决定是否重画顶部条(配合脏区/整帧判断)。 */ int meow_ui_sys_statusbar_force(void);