159 lines
7.2 KiB
C
159 lines
7.2 KiB
C
/* test_host_icon.c — 宿主最小 harness:复现主界面卡片(menu_draw_grid_cell)的
|
||
* 「卡底 → 图标 → 名称」绘制序列(与实际菜单同序),断言图标区像素非空。
|
||
*
|
||
* 背景:真机「应用图标完全不渲染(连首字母占位都无)」。本 harness 用真实 SDK(gfx+img)
|
||
* 按实际调用顺序绘制,对「有图(meow_ui_img_cover 不透明 226×226)」与「无图(primary
|
||
* 圆角块占位)」两分支各断言图标区含非背景像素;另转 PPM 目检。
|
||
*
|
||
* 编译(在 patch_v2/meow_launcherd 下):
|
||
* gcc -o test_host_icon test_host_icon.c ../sdk/test_host_stub.c \
|
||
* ../sdk/meow_ui_gfx.c ../sdk/meow_ui_sys.c ../sdk/meow_ui_theme.c \
|
||
* ../sdk/meow_ui_vol.c ../sdk/meow_ui_log.c ../sdk/meow_ui_widget.c \
|
||
* ../sdk/meow_ui_input.c ../sdk/meow_ui_activity.c ../sdk/meow_ui_dialog.c \
|
||
* ../sdk/meow_ui_ime.c ../sdk/meow_ui_draw.c ../sdk/meow_ui_view.c \
|
||
* ../sdk/meow_ui_img.c ../sdk/meow_notify_ipc.c ../sdk/meow_ui_media.c \
|
||
* ../sdk/stb_image.c -I../sdk -I. -DMEOW_UI_HOST_TEST -pthread -lm
|
||
* 运行:MEOW_UI_DUMP=/tmp/icon.ppm ./test_host_icon
|
||
*/
|
||
#include "meow_ui.h"
|
||
#include "meow_ui_internal.h" /* meow_ui_back_buf/pitch/bpp + meow_gfx_fill_round */
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <assert.h>
|
||
|
||
/* 与 launcher 主题色(dark)对齐 */
|
||
#define TH_SURFACE_CONTAINER 0x263038
|
||
#define TH_PRIMARY 0x4A6A9A
|
||
/* 不透明图标填充色 */
|
||
#define IMG_COLOR 0x336699
|
||
|
||
/* 与主菜单一致的几何常量(main_menu.c) */
|
||
#define MENU_GRID_RADIUS 16
|
||
#define MENU_GRID_ICON 44
|
||
#define MENU_GRID_CARD_H 112
|
||
#define MENU_GRID_COLS 2
|
||
#define MENU_GRID_PAD 12
|
||
#define MENU_GRID_GAP 10
|
||
#define FB_W 480
|
||
#define FB_H 720
|
||
|
||
static void rd_px(int x, int y, int *r, int *g, int *b)
|
||
{
|
||
unsigned char *bb = meow_ui_back_buf();
|
||
int line = meow_ui_back_buf_pitch(), bpp = meow_ui_back_buf_bpp();
|
||
if (!bb || x < 0 || y < 0) { *r = *g = *b = 0; return; }
|
||
if (bpp == 16) {
|
||
uint16_t px = *(uint16_t *)(bb + (size_t)y * line + (size_t)x * 2);
|
||
*r = (((px >> 11) & 0x1F) << 3) | ((px >> 11) & 0x1F) >> 2;
|
||
*g = (((px >> 5) & 0x3F) << 2) | ((px >> 5) & 0x3F) >> 4;
|
||
*b = ((px & 0x1F) << 3) | ((px & 0x1F) >> 2);
|
||
} else {
|
||
uint32_t px = *(uint32_t *)(bb + (size_t)y * line + (size_t)x * 4);
|
||
*r = (px >> 16) & 0xFF; *g = (px >> 8) & 0xFF; *b = px & 0xFF;
|
||
}
|
||
}
|
||
static int near2(int a, int b) { int d = a - b; if (d < 0) d = -d; return d <= 16; }
|
||
static int px_near(int x, int y, int r, int g, int b)
|
||
{
|
||
int rr, gg, bb; rd_px(x, y, &rr, &gg, &bb);
|
||
return near2(rr, r) && near2(gg, g) && near2(bb, b);
|
||
}
|
||
/* 区域内含「接近 target 色」的像素数 */
|
||
static int region_has(int x, int y, int w, int h, int r, int g, int b)
|
||
{
|
||
int cnt = 0;
|
||
for (int dy = 0; dy < h; dy++)
|
||
for (int dx = 0; dx < w; dx++)
|
||
if (px_near(x + dx, y + dy, r, g, b)) cnt++;
|
||
return cnt;
|
||
}
|
||
#define UNPK(c, rr, gg, bb) do { (rr) = ((c) >> 16) & 0xFF; (gg) = ((c) >> 8) & 0xFF; (bb) = (c) & 0xFF; } while (0)
|
||
|
||
/* 菜单图标绘制(menu_draw_icon):primary 圆角垫块始终垫底(MD3 图标 tile),
|
||
* 有图叠加 meow_ui_img_cover;无图叠加首字母。透明显图时垫块仍露出,图标区绝不空白。 */
|
||
static void menu_draw_icon_like(meow_img *icon, int x, int y, int sz)
|
||
{
|
||
meow_gfx_fill_round(x, y, sz, sz, sz * 3 / 10, TH_PRIMARY);
|
||
if (icon) { meow_ui_img_cover(x, y, sz, icon); return; }
|
||
}
|
||
|
||
/* 复现 menu_draw_grid_cell 的绘制序列(卡底 → 图标;名称与图标区隔离,无关像素) */
|
||
static void draw_grid_cell(int x, int y, int w, int h, meow_img *icon)
|
||
{
|
||
meow_gfx_fill_round(x, y, w, h, MENU_GRID_RADIUS, TH_SURFACE_CONTAINER);
|
||
int sz = (h > MENU_GRID_ICON + 40) ? MENU_GRID_ICON : h - 40;
|
||
int icx = x + (w - sz) / 2, icy = y + 12;
|
||
menu_draw_icon_like(icon, icx, icy, sz);
|
||
}
|
||
|
||
int main(void)
|
||
{
|
||
setbuf(stdout, NULL); /* 立即冲刷,abort 前也能看到 printf */
|
||
setenv("MEOW_UI_DUMP", "/tmp/icon.ppm", 1);
|
||
meow_ui_opts o = { FB_W, FB_H };
|
||
assert(meow_ui_init(&o) == 0);
|
||
assert(meow_ui_width() == FB_W && meow_ui_height() == FB_H);
|
||
|
||
int apps_top = 130; /* 模拟主菜单 app 区顶缘 */
|
||
int cx = MENU_GRID_PAD, cy = apps_top;
|
||
int cw = (FB_W - 2 * MENU_GRID_PAD - (MENU_GRID_COLS - 1) * MENU_GRID_GAP) / MENU_GRID_COLS;
|
||
int ch = MENU_GRID_CARD_H;
|
||
int sz = (ch > MENU_GRID_ICON + 40) ? MENU_GRID_ICON : ch - 40;
|
||
int icx = cx + (cw - sz) / 2, icy = cy + 12;
|
||
|
||
/* ---------- 分支 A:有图(meow_ui_img_cover,不透明 226×226,meow_img_load_file) ---------- */
|
||
{
|
||
meow_img *im = meow_img_load_file("/tmp/icon226.png");
|
||
assert(im != NULL);
|
||
assert(meow_img_w(im) == 226 && meow_img_h(im) == 226);
|
||
|
||
meow_ui_clear(0x000000);
|
||
draw_grid_cell(cx, cy, cw, ch, im);
|
||
|
||
int tr, tg, tb; UNPK(IMG_COLOR, tr, tg, tb);
|
||
int got = region_has(icx, icy, sz, sz, tr, tg, tb);
|
||
printf("A(image 226x226 opaque): icon region(%d,%d %dx%d) img-color px = %d\n",
|
||
icx, icy, sz, sz, got);
|
||
assert(got > 0 && "meow_ui_img_cover 未能把不透明图标画进图标区");
|
||
|
||
int sr, sg, sb; UNPK(TH_SURFACE_CONTAINER, sr, sg, sb);
|
||
int cardpx = region_has(icx, icy, sz, sz, sr, sg, sb);
|
||
printf(" card-color px inside icon region = %d\n", cardpx);
|
||
assert(cardpx == 0 && "图标区仍被卡底色占据(图标被盖掉/未画出)");
|
||
meow_img_free(im);
|
||
}
|
||
|
||
/* ---------- 分支 A':全透明图标(alpha=0)——修复后垫块垫底,图标区非空 ---------- */
|
||
{
|
||
meow_img *im = meow_img_load_file("/tmp/icon226_trans.png");
|
||
assert(im != NULL);
|
||
meow_ui_clear(0x000000);
|
||
draw_grid_cell(cx, cy, cw, ch, im);
|
||
int pr, pg, pb; UNPK(TH_PRIMARY, pr, pg, pb);
|
||
int got = region_has(icx, icy, sz, sz, pr, pg, pb);
|
||
printf("A'(transparent icon, fixed): icon region primary(tile) px = %d\n", got);
|
||
assert(got > 0 && "全透明图标不再被放过:垫块应画出(图标区非空)");
|
||
/* 垫块圆角角落会透出卡底色,属几何本性 */
|
||
meow_img_free(im);
|
||
}
|
||
|
||
/* ---------- 分支 B:无图(primary 圆角块占位) ---------- */
|
||
{
|
||
meow_ui_clear(0x000000);
|
||
draw_grid_cell(cx, cy, cw, ch, NULL);
|
||
int pr, pg, pb; UNPK(TH_PRIMARY, pr, pg, pb);
|
||
int got = region_has(icx, icy, sz, sz, pr, pg, pb);
|
||
printf("B(placeholder primary round): icon region primary px = %d\n", got);
|
||
assert(got > 0 && "占位圆角块未画进图标区");
|
||
/* 圆角块角落会透出卡底色——这是几何本性,非 bug;只要求主色像素显著多 */
|
||
int sr, sg, sb; UNPK(TH_SURFACE_CONTAINER, sr, sg, sb);
|
||
int cardpx = region_has(icx, icy, sz, sz, sr, sg, sb);
|
||
printf(" card-color px in icon region (round corners) = %d\n", cardpx);
|
||
assert(got > sz * sz * 3 / 4 && "占位圆角块覆盖面积过小(未真正画到图标区)");
|
||
}
|
||
|
||
printf("PASS test_host_icon (A image + B placeholder render in icon region)\n");
|
||
return 0;
|
||
}
|