/* statusbar.c — MeowOS launcher 拆分模块(LAUNCHER_SPLIT_PLAN 拆分)。*/ /* 本文件由拆分工具从 meow_launcherd.c 按职责搬移;逻辑与原文 0-diff(仅 static 可见性按跨模块需求调整)。*/ #include "meow_launcher_internal.h" int g_sb_icon_cy = SB_ICON_CY; /* 状态栏文字垂直锚 y(行首升线顶):(栏高-行高)/2 把文字垂直居中于 28px 栏; * 下限 1 防极端行高(>栏高)时算出负 y 溢出顶端(不越界优先)。 */ /* 状态栏 MD3 图标 blit:把 sb_icons.h 的 32x32 单通道 alpha 位图画进状态栏(fb = SDK back_buf)。 * x = 图标槽左缘(槽宽 SB_ICON_SIZE);fg = 24-bit RGB 前景色(主题 on_surface / on_surface_variant)。 * M2.46-2 视觉对齐(音量图标小一圈/下边距、图标与文字垂直中心): * - 先求该位图 ink 边界(阈值 32,忽略近透明抗锯齿);按 ink 边界在槽内水平居中,并把 ink 垂直 * 中心对齐到全局 g_sb_icon_cy(==状态栏文字中心),→ 所有图标共用同一光学中线,不再「偏下」。 * - ink_h>0 时对 ink 做等比缩放(绘制时最近邻采样,源位图不变)到该 ink 高:主图标统一用 * SB_ICON_INK,音量(volume_up ink 较矮)随之放大到与电量/亮度一致 → 不显「小一圈」。 * - ink_h==0 保持位图自然 ink 尺寸(仅居中):用于 WiFi 强弱档——较短 ink(少一格)本身即 * 「信号弱」语义,不可被等比拉大。 * 像素 = 前景与背景按 alpha 软边混合(a<8 跳过透明;a>=240 直写前景;其余按 a>>4 在 565 空间 * 插值),与 blit_pm_icon 同构——暗/亮主题下图标随状态栏底色一起换色。 */ void sb_blit_icon(int icon_idx, int x, uint32_t fg, int ink_h) { const unsigned char *src = sb_icons[icon_idx].data; uint16_t col = rgb565(fg); /* 1) ink 边界(含空图兜底) */ int minx = SB_ICON_SIZE, miny = SB_ICON_SIZE, maxx = -1, maxy = -1; for (int i = 0; i < SB_ICON_SIZE * SB_ICON_SIZE; i++) { if (src[i] >= 32) { int xx = i % SB_ICON_SIZE, yy = i / SB_ICON_SIZE; if (xx < minx) minx = xx; if (xx > maxx) maxx = xx; if (yy < miny) miny = yy; if (yy > maxy) maxy = yy; } } if (maxx < minx || maxy < miny) { minx = miny = 0; maxx = maxy = SB_ICON_SIZE - 1; } int ink_w = maxx - minx + 1, ink_h_n = maxy - miny + 1; int t_h = (ink_h > 0) ? ink_h : ink_h_n; /* 目标 ink 高 */ int t_w = ink_w * t_h / ink_h_n; if (t_w < 1) t_w = 1; if (t_w > SB_ICON_SIZE * 2) t_w = SB_ICON_SIZE * 2; /* 防御:等比极端上限 */ /* 2) 目标框左上:水平居中于 32px 槽;垂直中心 = g_sb_icon_cy */ int x0 = x + (SB_ICON_SIZE - t_w) / 2; int y0 = g_sb_icon_cy - t_h / 2; /* 3) 最近邻采样映射:目标 (dx,dy) ← 源 ink (minx+dx*ink_w/t_w, miny+dy*ink_h_n/t_h) */ for (int dy = 0; dy < t_h; dy++) { int ty = y0 + dy; if (ty < 0 || ty >= fb_yres) continue; int sy = miny + (dy * ink_h_n) / t_h; uint16_t *row = (uint16_t *)fb + ty * (fb_line / 2); for (int dx = 0; dx < t_w; dx++) { int tx = x0 + dx; if (tx < 0 || tx >= fb_xres) continue; int sx = minx + (dx * ink_w) / t_w; int a = src[sy * SB_ICON_SIZE + sx]; if (a < 8) continue; /* 透明像素跳过 */ uint16_t bg = row[tx]; if (a >= 240) { row[tx] = col; continue; } int a4 = a >> 4; /* 0..15 */ int r = ((col >> 11) * a4 + ((bg >> 11) & 0x1F) * (16 - a4)) >> 4; int g = (((col >> 5) & 0x3F) * a4 + ((bg >> 5) & 0x3F) * (16 - a4)) >> 4; int b = ((col & 0x1F) * a4 + (bg & 0x1F) * (16 - a4)) >> 4; row[tx] = (uint16_t)((r << 11) | (g << 5) | b); } } } /* ---- Stage-One 状态栏收敛:launcher 不再自绘状态栏,统一由 SDK 全局状态栏绘制 ---- * launcher 系统界面(主界面/设置页/电源菜单/通知中心)顶部 28px 状态栏改由 SDK 的 * meow_ui_sys_statusbar_render()(present() 时合成,z 最顶)绘制。launcher 侧只保留三个 * 入口(paint_sb_clock/paint_sb_right/draw_statusbar,调用点遍布主界面/设置页/通知中心/ * 音量/亮度/主题变更/1s 时钟),其职责从「自绘」改为「把权威状态喂进 SDK + 标脏顶条」。 * 依据(devdocs/plan/LAUNCHER_SDK_REWRITE.md): * - launcher 不跑 SDK 事件循环 → SDK 的 meow_ui_sys_refresh() 不在 launcher 触发,数据 * 必须由 launcher 喂。g_sys(meow_sys_refresh/light + 事件路径维护)是权威源,尤其 * 亮度/音量(写入方=launcher)。 * - SDK 主题是缓存的 → 喂前 meow_theme_reload() 逼重读 settings,状态栏跟手 launcher 换肤。 * - 标脏顶条 (0,0,xres,28) → present() 时 SDK 重画顶条;SDK 只在「数据变(force)/顶条被触及/ * 收合过渡」才重画,天然满足「状态栏只在变化时重绘」。 */ static void sb_sdk_refresh(void) { meow_theme_reload(); /* SDK 状态栏主题随 launcher 换肤(重读 settings) */ meow_ui_feed f; f.batt = g_sys.batt; f.charging = g_sys.charging; f.wifi_on = g_sys.wifi_on; f.wifi_connected = g_sys.wifi_connected; f.wifi_level = g_sys.wifi_level; f.bt_seen = g_sys.bt_seen; f.bt_on = g_sys.bt_on; f.vol = g_sys.vol; f.brightness = g_sys.brightness; meow_ui_sys_feed(&f); /* 权威快照喂入 + 置 force(顶条必重画) */ meow_dirty_add(0, SB_BAR_Y, fb_xres, SB_BAR_H); /* 标脏顶条 → present() 时 SDK 重画 */ } /* 三个入口(调用点不动):现在驱动 SDK 全局状态栏(唯一绘制者),不再自绘。 */ void paint_sb_clock(void) { sb_sdk_refresh(); } void paint_sb_right(void) { sb_sdk_refresh(); } void draw_statusbar(void) { sb_sdk_refresh(); } /* 对齐原语义:整条状态栏 → SDK 绘制 */ /* 上次读到的 App 顶条模式(用于在 launch_app waitpid 循环里判「模式新变 → 立即叠一次」)。 * 高整文件作用域;每次启动 App 前重置为 -1(强制首帧同步一次)。 */ int g_sb_mode_last = -1;