feat(lyric): 批5 封面双色渐变取色 — SDK meow_img_color纯整数分桶主色+次色(副采样≤3.6k零分配)+launcher播放页/歌词页set_colors注入渐变主题+无封面回退全局主题+meow_lyric_view灰阶随覆盖cur修正;宿主C1-C7全过,0warning,未并入meow_ui.a
This commit is contained in:
1 parent
a3679e3688
commit
1f6d390e1c
6 files changed
+541
-22
No files matched your search
@@ -29,7 +29,7 @@ SYSROOT="$ROOT/.tools/mipsel-linux-muslsf-cross/mipsel-linux-muslsf"
|
||||
font_theme.c keys.c util.c meow_dep.c \
|
||||
meow_touch.c meow_settings.c meow_notif.c meow_media.c meow_bgplay.c \
|
||||
meow_ams_start.c lock_screen.c lock_screen_ui.c lock_settings.c \
|
||||
"../sdk/meow_lyric.c" "../sdk/meow_lyric_view.c" \
|
||||
"../sdk/meow_lyric.c" "../sdk/meow_lyric_view.c" "../sdk/meow_img_color.c" \
|
||||
"../sdk/meow_ui.a" "$SYSROOT/lib/libz.a" -lpthread -o meow_launcherd
|
||||
echo "== meow_launcherd =="
|
||||
ls -la meow_launcherd
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "meow_launcher_internal.h"
|
||||
#include "np_gesture.h" /* 批4:双页方向感知手势决策(header-only,宿主可单测) */
|
||||
#include "meow_lyric_view.h" /* 批2控件:歌词页渲染(批4接入,数据批3 meow_media_lyric_*) */
|
||||
#include "meow_img_color.h" /* 批5:封面双色取色原语(独立源码,不并入 meow_ui.a) */
|
||||
|
||||
|
||||
#define NP_COVER 300 /* 封面边长(方,居中) */
|
||||
@@ -66,6 +67,56 @@ static void np_cover_load(const meow_media_session_t *s)
|
||||
g_np_cover = meow_img_load_file(path);
|
||||
}
|
||||
|
||||
/* ==================================================================
|
||||
* 批5:封面双色取色(主色+次色)→ 播放页/歌词页动态主题。
|
||||
* - 何时取:进入 Now Playing 页 / 封面路径变化时(np_cover_theme_update 幂等,按路径缓存)。
|
||||
* - 取色成本:meow_img_duocolor 内部自适副采样(等效缩略图,≤~3.6k 样本),不额外解码/分配。
|
||||
* - 缓存:按 artwork 路径;路径未变不重取(g_np_cc_valid + g_np_cc_path)。
|
||||
* - 回退:无封面/取色失败(g_np_cc_valid=0)→ 歌词页 set_colors(NULL) 用 meow_theme 默认;
|
||||
* 播放页背景/文字走 s_ui_theme() 主题面。
|
||||
* ================================================================== */
|
||||
static meow_img_color_theme g_np_cc;
|
||||
static int g_np_cc_valid = 0;
|
||||
static char g_np_cc_path[200] = "";
|
||||
|
||||
/* 校验/刷新取色缓存(封面路径变化才重取;幂等)。 */
|
||||
static void np_cover_theme_update(void)
|
||||
{
|
||||
const meow_media_session_t *s = meow_media_current();
|
||||
const char *art = s ? s->artwork : "";
|
||||
if (g_np_cc_valid && strcmp(g_np_cc_path, art) == 0) return; /* 缓存命中 */
|
||||
snprintf(g_np_cc_path, sizeof g_np_cc_path, "%s", art);
|
||||
g_np_cc_valid = 0;
|
||||
if (!g_np_cover || !art[0]) return; /* 无封面 → 回退主题 */
|
||||
uint32_t mainc = 0, secondc = 0;
|
||||
if (meow_img_duocolor(g_np_cover, &mainc, &secondc) != 0) return; /* 取色失败 → 回退主题 */
|
||||
meow_img_color_derive(mainc, secondc, meow_theme_get(), &g_np_cc);
|
||||
g_np_cc_valid = 1;
|
||||
}
|
||||
|
||||
/* 把封面取色注入歌词页(无取色 → NULL 回退 meow_theme 默认)。 */
|
||||
static void np_apply_lyric_colors(void)
|
||||
{
|
||||
if (!g_np_lyric) return;
|
||||
meow_lyric_view_set_colors(g_np_lyric, g_np_cc_valid ? &g_np_cc.lyr : NULL);
|
||||
}
|
||||
|
||||
/* 竖向双色渐变填充(无 GPU,逐行整数插值;封面主题背景用)。 */
|
||||
static void np_fill_gradient(int x, int y, int w, int h, uint32_t top, uint32_t bottom)
|
||||
{
|
||||
if (w <= 0 || h <= 0) return;
|
||||
int tr = (top >> 16) & 255, tg = (top >> 8) & 255, tb = top & 255;
|
||||
int br = (bottom >> 16) & 255, bg = (bottom >> 8) & 255, bb = bottom & 255;
|
||||
int span = h - 1;
|
||||
for (int yy = 0; yy < h; yy++) {
|
||||
int t = span > 0 ? yy * 255 / span : 0;
|
||||
int r = tr + ((br - tr) * t + 128) / 255;
|
||||
int g = tg + ((bg - tg) * t + 128) / 255;
|
||||
int b = tb + ((bb - tb) * t + 128) / 255;
|
||||
fill_rect(x, y + yy, w, 1, ((uint32_t)r << 16) | ((uint32_t)g << 8) | (uint32_t)b);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0 /* ================================================================
|
||||
* M7.0b 退役:Now Playing 手绘控制钮/进度条改走 SDK 控件(meow_iconbtn +
|
||||
* meow_progress),命中/状态/进度全由 SDK 接管;保留作回退位(删除 #if 0 行恢复旧手绘)。
|
||||
@@ -166,13 +217,14 @@ static void np_widgets_create(void)
|
||||
g_np_init = 1;
|
||||
}
|
||||
|
||||
/* 主题刷新:播放钮底色/图标随当前主题(明暗/风格切换后跟手)。 */
|
||||
/* 主题刷新:播放钮底色/图标随当前主题(明暗/风格切换后跟手);批5 封面取色时随 accent。 */
|
||||
static void np_refresh_theme(void)
|
||||
{
|
||||
if (!g_np_init) return;
|
||||
const meow_theme *th = meow_theme_get();
|
||||
meow_widget_opts op; memset(&op, 0, sizeof op);
|
||||
op.bg = th->primary; op.fg = th->onPrimary;
|
||||
op.bg = g_np_cc_valid ? g_np_cc.accent : th->primary;
|
||||
op.fg = g_np_cc_valid ? g_np_cc.accent_fg : th->onPrimary;
|
||||
if (g_np_play) meow_widget_set_opts(g_np_play, &op);
|
||||
if (g_np_pause) meow_widget_set_opts(g_np_pause, &op);
|
||||
}
|
||||
@@ -201,8 +253,9 @@ static void np_draw_progress(const meow_media_session_t *s, uint32_t pos, const
|
||||
unsigned dm = (s->dur_ms ? s->dur_ms : 0) / 60000u, ds = (s->dur_ms ? s->dur_ms : 0) % 60000u / 1000u;
|
||||
snprintf(l, sizeof l, "%u:%02u", lm, ls);
|
||||
snprintf(rbuf, sizeof rbuf, "%u:%02u", dm, ds);
|
||||
ui_draw(NP_PROG_X, NP_TIME_Y, l, th->on_surface_variant, 16);
|
||||
ui_draw(NP_PROG_X + NP_PROG_W - ui_width(rbuf, 16), NP_TIME_Y, rbuf, th->on_surface_variant, 16);
|
||||
uint32_t tcol = g_np_cc_valid ? g_np_cc.fg_dim : th->on_surface_variant;
|
||||
ui_draw(NP_PROG_X, NP_TIME_Y, l, tcol, 16);
|
||||
ui_draw(NP_PROG_X + NP_PROG_W - ui_width(rbuf, 16), NP_TIME_Y, rbuf, tcol, 16);
|
||||
}
|
||||
|
||||
/* ==================================================================
|
||||
@@ -238,14 +291,20 @@ static void np_lyric_refresh(const meow_media_session_t *s)
|
||||
g_np_lyric_last_valid = valid;
|
||||
}
|
||||
|
||||
/* 歌词页整页绘制:铺 theme surface 底 → lyric_view(自绘 scrim + 歌词/空态)。 */
|
||||
/* 歌词页整页绘制:铺封面取色渐变(或 theme surface)底 → lyric_view(自绘 scrim + 歌词/空态)。 */
|
||||
static void np_draw_lyric_page(int redraw_sb)
|
||||
{
|
||||
const meow_ui_theme_t *th = s_ui_theme();
|
||||
int W = fb_xres, H = fb_yres;
|
||||
if (!g_np_init) np_widgets_create();
|
||||
if (redraw_sb) fill_rect(0, 0, W, SB_BAR_H, th->surface);
|
||||
fill_rect(0, SB_BAR_H, W, H - SB_BAR_H, th->surface);
|
||||
/* 批5:封面取色背景(主→次渐变)或主题面;并注入歌词页 set_colors。 */
|
||||
np_cover_theme_update();
|
||||
if (g_np_cc_valid)
|
||||
np_fill_gradient(0, SB_BAR_H, W, H - SB_BAR_H, g_np_cc.bg_top, g_np_cc.bg_bottom);
|
||||
else
|
||||
fill_rect(0, SB_BAR_H, W, H - SB_BAR_H, th->surface);
|
||||
np_apply_lyric_colors();
|
||||
np_lyric_refresh(meow_media_current());
|
||||
if (g_np_lyric)
|
||||
meow_widget_draw(meow_lyric_view_widget(g_np_lyric));
|
||||
@@ -264,10 +323,10 @@ static void np_draw_page(int redraw_sb)
|
||||
return;
|
||||
}
|
||||
if (redraw_sb) fill_rect(0, 0, W, SB_BAR_H, th->surface);
|
||||
fill_rect(0, SB_BAR_H, W, H - SB_BAR_H, th->surface);
|
||||
const meow_media_session_t *s = meow_media_current();
|
||||
if (!s || s->state == MEOW_MEDIA_STOPPED) {
|
||||
/* 空态占位(M7.0b 文案走 meow_str,未知 id 回退中文) */
|
||||
fill_rect(0, SB_BAR_H, W, H - SB_BAR_H, th->surface);
|
||||
const char *t1 = meow_str_zh("np.not_playing", "未在播放");
|
||||
ui_draw((W - ui_width(t1, 26)) / 2, 300, t1, th->on_surface_variant, 26);
|
||||
const char *t2 = meow_str_zh("np.open_app_hint", "打开播放 App 以显示正在播放");
|
||||
@@ -278,6 +337,14 @@ static void np_draw_page(int redraw_sb)
|
||||
return;
|
||||
}
|
||||
np_cover_load(s);
|
||||
/* 批5:封面取色(主/次色)+ 背景渐变或主题面;并注入歌词页 set_colors。
|
||||
* np_cover_theme_update 幂等(封面路径不变不重取);无封面/取色失败回退 meow_theme。 */
|
||||
np_cover_theme_update();
|
||||
if (g_np_cc_valid)
|
||||
np_fill_gradient(0, SB_BAR_H, W, H - SB_BAR_H, g_np_cc.bg_top, g_np_cc.bg_bottom);
|
||||
else
|
||||
fill_rect(0, SB_BAR_H, W, H - SB_BAR_H, th->surface);
|
||||
np_apply_lyric_colors();
|
||||
/* 封面:解码缓存 + 圆角裁方;无封面回退主题色占位 + 首字 */
|
||||
if (g_np_cover) {
|
||||
meow_gfx_fill_round(NP_COVER_X - 6, NP_COVER_Y - 6, NP_COVER + 12, NP_COVER + 12, 18, th->surface_container);
|
||||
@@ -290,11 +357,11 @@ static void np_draw_page(int redraw_sb)
|
||||
ui_draw(NP_COVER_X + (NP_COVER - cw) / 2, NP_COVER_Y + (NP_COVER - meow_font_line_height(22)) / 2,
|
||||
t, meow_theme_get()->onPrimary, 22);
|
||||
}
|
||||
/* 元数据 */
|
||||
np_center_text(NP_TITLE_Y, s->title, 26, th->on_surface, W - 40);
|
||||
np_center_text(NP_ARTIST_Y, s->artist, 18, th->on_surface_variant, W - 60);
|
||||
/* 元数据(批5:封面取色时文字随 fg/fg_dim,否则主题面) */
|
||||
np_center_text(NP_TITLE_Y, s->title, 26, g_np_cc_valid ? g_np_cc.fg : th->on_surface, W - 40);
|
||||
np_center_text(NP_ARTIST_Y, s->artist, 18, g_np_cc_valid ? g_np_cc.fg_dim : th->on_surface_variant, W - 60);
|
||||
if (s->album[0])
|
||||
np_center_text(NP_ALBUM_Y, s->album, 16, th->on_surface_variant, W - 80);
|
||||
np_center_text(NP_ALBUM_Y, s->album, 16, g_np_cc_valid ? g_np_cc.fg_dim : th->on_surface_variant, W - 80);
|
||||
/* 进度(SDK meow_progress) */
|
||||
uint32_t pos = meow_media_display_pos(s);
|
||||
np_draw_progress(s, pos, th);
|
||||
@@ -564,4 +631,6 @@ void run_now_playing(struct app *apps, int napps)
|
||||
kp_close(&kp_power);
|
||||
if (g_np_cover) { meow_img_free(g_np_cover); g_np_cover = NULL; }
|
||||
g_np_cover_path[0] = 0;
|
||||
g_np_cc_valid = 0; /* 批5:退出清取色缓存,下次进入重新取 */
|
||||
g_np_cc_path[0] = 0;
|
||||
}
|
||||
Reference in new issue
Block a user