/* meow_launcherd/test_bg_row_card.c — 宿主验证:后台管理页(bg_page)MD3 圆角卡行 + 行内杀按钮 * 的几何与命中(纯整数运算,不链 SDK / 不开设备): * gcc -Wall -Wextra test_bg_row_card.c -o test_bg_row_card && ./test_bg_row_card * * 断言集(对应「相邻 item 顶之间 = item 高 + gap」的可见形式): * ① 卡高 = 行高 - BGM_CARD_GAP;卡在其行高内上下对称内缩 gap/2(行中心=卡中心); * ② 相邻卡顶间距 = SUB_ITEM_H(= 卡高 + gap;SDK 行距不变),卡片间可见外距 = gap; * ③ 杀按钮垂直居中于卡(中心=卡中心=行中心),完整落卡内,右缘距行右 12px; * ④ 命中不破:卡内缩后按钮几何不变(相对整行视口)——按钮区内点按命中(1), * 行体/卡内空白点按不命中(0);命中矩形仍为整行距; * ⑤ 滚动偏移只整体平移,不改变上述间距/对称/命中。 * * 几何公式与 patch_v2/meow_launcherd/bg_page.c 的 bgm_row_card_y/bgm_row_card_h/bgm_btn_rect 同源。 */ #include #include #define SUB_ITEM_H 56 /* 行距(SDK listview item_h,subpage.c,不变) */ #define BGM_CARD_GAP 8 #define BGM_BTN_W 46 #define BGM_BTN_H 34 /* 与 bg_page.c bgm_row_card_y / bgm_row_card_h 同源(上下对称内缩)。 */ static int bgm_row_card_y(int row_top) { return row_top + BGM_CARD_GAP / 2; } static int bgm_row_card_h(int h) { return h - BGM_CARD_GAP; } /* 与 bg_page.c bgm_btn_rect 同源(按钮垂直居中于卡;卡中心=行中心 → 命中不破)。 */ static void bgm_btn_rect(int rx, int ry, int rw, int rh, int *bx, int *by, int *bw, int *bh) { *bw = BGM_BTN_W; *bh = BGM_BTN_H; *bx = rx + rw - 12 - BGM_BTN_W; *by = bgm_row_card_y(ry) + (bgm_row_card_h(rh) - BGM_BTN_H) / 2; } /* 行顶 = list_y + idx*item - off(SDK listview 布局:行距=item)。 */ static int row_top(int idx, int item, int list_y, int off) { return list_y + idx * item - off; } /* 复刻 bgm_row_tap 的按钮命中判定(仅几何):命中按钮区=1,行体/卡内空白=0。 */ static int btn_hit(int tx, int ty, int rx, int ry, int rw, int rh) { int bx, by, bw, bh; bgm_btn_rect(rx, ry, rw, rh, &bx, &by, &bw, &bh); if (tx < bx || tx >= bx + bw || ty < by || ty >= by + bh) return 0; return 1; } int main(void) { const int item = SUB_ITEM_H; const int gap = BGM_CARD_GAP; const int list_y = 100; /* 内容区顶缘(SUB_CONT_TOP 等值,任意值皆可) */ const int rw = 480; /* 行视口宽(fb_xres,480×720) */ const int rx = 0; /* 行视口左缘 */ int y0 = bgm_row_card_y(row_top(0, item, list_y, 0)); int y1 = bgm_row_card_y(row_top(1, item, list_y, 0)); int h = bgm_row_card_h(item); /* ① 卡相对行顶对称内缩 gap/2;卡高=item-gap;卡高+gap=item */ assert(y0 == list_y + gap / 2); assert(h == item - gap); assert(h + gap == item); /* ① 相邻卡顶间距 = item(顶到顶 = 卡高 + gap) */ assert(y1 - y0 == item); /* ② 卡片间可见外距 = gap(卡 0 底 到 卡 1 顶) */ assert(y1 - (y0 + h) == gap); /* ③ 卡中心 == 行中心(内容按行高居中 → 落卡中心) */ assert(y0 - gap / 2 + item / 2 == y0 + h / 2); /* 下行底到卡底 = gap/2(下对称) */ assert((list_y + item) - (y0 + h) == gap / 2); /* ③④ 杀按钮:相对整行视口定位,垂直居中于卡(中心=卡中心=行中心),完整落卡内, * 右缘距行右 12px;滚动偏移只平移,不改变以上(③④⑤合并循环)。 */ for (int off = 0; off <= item; off += item / 2) { int r0 = row_top(0, item, list_y, off); int bx, by, bw, bh; bgm_btn_rect(rx, r0, rw, item, &bx, &by, &bw, &bh); int card_top = bgm_row_card_y(r0); int card_bot = card_top + bgm_row_card_h(item); int row_cy = r0 + item / 2; int card_cy = card_top + bgm_row_card_h(item) / 2; /* 按钮完整落卡内(含圆角内边距;上下由卡限,左右由行限) */ assert(bx >= rx && bx + bw <= rx + rw); assert(by >= card_top && by + bh <= card_bot); /* 按钮中心 = 卡中心 = 行中心(垂直) */ assert(by + bh / 2 == card_cy); assert(by + bh / 2 == row_cy); /* 按钮右缘距行右 12px(与绘制一致) */ assert(rx + rw - (bx + bw) == 12); /* ④ 命中:按钮中心 → 命中(1);卡内空白(左上圆角内) / 行体左缘 → 不命中(0) */ assert(btn_hit(bx + bw / 2, by + bh / 2, rx, r0, rw, item) == 1); assert(btn_hit(card_top + 2, card_top + 2, rx, r0, rw, item) == 0); assert(btn_hit(rx + 16, row_cy, rx, r0, rw, item) == 0); /* 卡上/下外侧(gap 带内)点按 → 不命中(命中仍按整行距,含 gap 带) */ assert(btn_hit(rx + rw / 2, r0 + gap / 2 - 1, rx, r0, rw, item) == 0); } printf("PASS bg_row_card_gap=%d card_h=%d top2top=%d visible_gap=%d " "btn_in_card=1 btn_center==row_center=1 hit_unbroken=1\n", gap, h, item, gap); return 0; }