feat(sdk): 批2 meow_lyric_view 歌词页渲染控件 — 上收ncm成熟布局(活动行纯白/灰阶/偏上锚定/翻译行不叠行/折行/点行seek),布局命中绘制同源,宿主L1-L7全过,预留批5取色set_colors,暂不并入meow_ui.a

This commit is contained in:
AskaEth committed 2026-09-03 17:56:27 +08:00
1 parent 4827cc8d92
commit dce12c63a2
4 files changed
+787

No files matched your search

+110
View File
@@ -0,0 +1,110 @@
/*
* meow_lyric_view.h — MeowOS SDK 通用歌词页渲染控件(可复用,供 launcher Now Playing 与 ncm 共用)。
*
* 定位:把 ncm_app/app/ui/player.c 已成熟(agent-380 修好 s_lyr_bh)的歌词页布局上收成 SDK 控件。
* 能力对齐 ncm 歌词页:活动行纯白(居中偏上锚定)、上下行按行距逐级灰阶、翻译行紧跟原文行不叠行
* (块高含翻译行)、超宽折行(中西文兼容)、上方保底 ≥above_min 行已过、总视觉行数 ≤max_rows、
* 点行 seek 命中与绘制一致(同一布局函数)。
*
* 数据来源:**绑定批1 meow_lyric**(解析/查询 API:meow_lyric_count/line_at/line_text/line_tl/line_time,
* 全局单例,线程安全)+ 播放位置(meow_lyric_view_set_pos)。宽度测量用回调注入
* (`meow_lyric_width_fn`,包 meow_ui_text_width 的包装;宿主测试传自己的测量函数)。
*
* 控件形态:内部持一个 `meow_widget`(W_CUSTOM 自定义画布),经 meow_lyric_view_widget() 取出供
* meow_widget_draw/hit/注册;render_cb/hit_cb 都由本控件自绘/自判。App 也可只用纯查询接口
* (meow_lyric_view_visible/hit_line)在自绘流程里复用布局逻辑。
*
* 主题:用 SDK 全局 meow_theme 为默认(明暗背景 scrim、活动行 onSurface=dark 纯白、灰阶递减),
* 为批5「封面取色动态主题」预留 meow_lyric_view_set_colors 覆盖入口(字段 0=仍用主题默认)。
*
* 依赖:纯 SDK(meow_ui.h + meow_lyric.h),不引任何 ncm 私有符号;可链 meow_ui.a 使用,
* 亦可宿主 gcc 单测(同 test_now_playing_widgets 链法)。本头为**独立公共头**(仿 meow_ui_view.h
* 模式,不随 meow_ui.h 伞头发布),App 显式 `#include "meow_lyric_view.h"`。
*
* 命名:API 一律 `meow_lyric_view_*`(对齐 SDK 规范);控件内布局/绘制/命中共享同一
* meow_lyric_view_visible 计算,保证「点行 seek 命中与绘制一致」。
*/
#ifndef MEOW_LYRIC_VIEW_H
#define MEOW_LYRIC_VIEW_H
#include "meow_ui.h" /* meow_widget / meow_theme / meow_ui_text 等 */
#include "meow_lyric.h" /* meow_lyric_width_fn + 行查询 API(批1) */
#ifdef __cplusplus
extern "C" {
#endif
typedef struct meow_lyric_view meow_lyric_view;
/* 可见层数硬上限(对齐 ncm LYR_MAX_ROWS;数组按此定容,运行时 layout.max_rows 不得越此)。 */
#define MEOW_LYRIC_VIEW_MAX_ROWS 9
/* ---- 可见条目(布局/命中/绘制共用,宿主可测)----
* ent=歌词行下标;rw=原文折行段数;bh=块高(子行数)=rw + 当前行翻译占 1(其余条目 bh=rw);
* sz=该条目字号;y=块顶 y(绝对屏幕坐标)。 */
typedef struct meow_lyric_view_vis {
int ent;
int rw;
int bh;
int sz;
int y;
} meow_lyric_view_vis;
/* ---- 主题色覆盖(批5 封面取色动态主题预留)----
* 全部字段:0(scrim_alpha<0)= 用 meow_theme 内建默认;显式值 = 覆盖。
* 默认映射:scrim=th->scrim(黑叠加在封面之上,alpha 176);cur=th->onSurface(dark=0xFFFFFF 纯白);
* gray[0]=cur,gray[1..5]=对 cur 逐级缩灰(对纯白即 ncm 的 {BBBBBB,929292,808080,6A6A6A,555555})。
* scrim_alpha==0 = 不画 scrim(App 已自绘封面/叠加层时用)。 */
typedef struct meow_lyric_view_colors {
uint32_t scrim; /* 背景 scrim 色(半透明叠加在封面之上) */
uint32_t cur; /* 活动行色(默认 th->onSurface;dark 下=纯白) */
uint32_t gray[6]; /* 距活动行 0..5 灰阶;gray[0]=cur。字段 0=自动递减 */
int scrim_alpha; /* scrim 透明度 0-255;<0=默认(176);0=不画 scrim */
} meow_lyric_view_colors;
/* ---- 布局参数(对齐 ncm;NULL=内建默认)---- */
typedef struct meow_lyric_view_layout {
int pad; /* 左边距(默认 24) */
int sub_lh; /* 子行高(默认 44) */
int cur_sz; /* 活动行字号(默认 28) */
int oth_sz; /* 上下行字号(默认 24) */
int tl_sz; /* 当前行翻译字号(默认 20) */
int max_rows; /* 可见视觉行数上限(默认 9;≤MEOW_LYRIC_VIEW_MAX_ROWS) */
int above_min; /* 活动行上方保底已过行数(默认 2) */
int above_off; /* 活动行块中心相对视图中线偏上 px(默认 50,需求3 偏上锚定) */
} meow_lyric_view_layout;
/* 点行 seek 回调:meow_lyric_view_set_on_seek 设置;命中某行后回调 line_time(ms)。 */
typedef void (*meow_lyric_seek_fn)(int64_t ms, void *ctx);
/* ---- 生命周期 ---- */
meow_lyric_view *meow_lyric_view_create(int x, int y, int w, int h,
meow_lyric_width_fn width, void *width_ctx);
void meow_lyric_view_free(meow_lyric_view *lv);
/* 底层 W_CUSTOM meow_widget:App 用它做 draw/hit/注册(launcher 控件模型)。 */
meow_widget *meow_lyric_view_widget(const meow_lyric_view *lv);
/* ---- 数据绑定 ---- */
void meow_lyric_view_set_pos(meow_lyric_view *lv, int64_t pos_ms); /* 播放器位置(ms) */
/* ---- 主题/布局/空态 ---- */
void meow_lyric_view_set_colors(meow_lyric_view *lv, const meow_lyric_view_colors *c); /* NULL=回主题默认 */
void meow_lyric_view_set_layout(meow_lyric_view *lv, const meow_lyric_view_layout *ls); /* NULL=回内建默认 */
void meow_lyric_view_set_empty(meow_lyric_view *lv, const char *txt); /* 无歌词占位文案;NULL=默认 */
/* 点行 seek(widget hit 命中时回调;App 也可只用 meow_lyric_view_hit_line 自行 seek)。 */
void meow_lyric_view_set_on_seek(meow_lyric_view *lv, meow_lyric_seek_fn cb, void *ctx);
/* ---- 查询 ——
* cur_color / line_color:取该视图生效(主题默认或覆盖)的活动行色 / 距活动行 dist(0..5) 行色。
* visible:按 pos_ms 计算可见条目布局(与绘制/命中同一算法)写入 out[≤cap],返回条目数(≤0=空/无活动行)。
* hit_line:点 (x,y) 命中某歌词行下标(与绘制一致的布局;块外就近取整);未命中返回 -1。 */
uint32_t meow_lyric_view_cur_color(const meow_lyric_view *lv);
uint32_t meow_lyric_view_line_color(const meow_lyric_view *lv, int dist);
int meow_lyric_view_hit_line(meow_lyric_view *lv, int x, int y);
int meow_lyric_view_visible(meow_lyric_view *lv, int64_t pos_ms,
meow_lyric_view_vis *out, int cap);
#ifdef __cplusplus
}
#endif
#endif /* MEOW_LYRIC_VIEW_H */