feat(sdk): 绘制期通用clip + view递归/on_event接线 (agent-195) — ①栈式clip rect(g_clip_stack[16]), 所有写像素原语过clip, meow_widget_draw push/pop控件矩形(含W_CUSTOM, 根治越界脏区), IME/模态顶层全屏不受影响 ②view enter/leave递归children + meow_view_dispatch_event(z降序子>父命中即消费); hello App层显式驱动退役
meow_ui.a→da4d3a7d; hello→c655ba43; 宿主4套件全PASS(含clip越界断言+view递归断言) 出入: W_SLIDER拇指在max处被裁(既有几何瑕疵可见化,待修); on_draw祖先已进入即画
This commit is contained in:
1 parent
b2e7cc8c70
commit
32a6a8ed1e
14 files changed
+257
-44
No files matched your search
@@ -62,6 +62,48 @@ static int g_dirty[/*MUI_DIRTY_MAX*/12][4]; /* [x,y,w,h] */
|
||||
static int g_ndirty = 0;
|
||||
static int g_dirty_full = 1;
|
||||
|
||||
/* ---- 绘制期裁剪(clip rect,§3;默认全屏)----
|
||||
* 栈式嵌套:push 与当前 clip 求交后压栈,pop 恢复。写像素原语(put_px / put_px_blend /
|
||||
* fill_rect / fill_rect_alpha / round / circle / ring / blit_icon / blit_rgba / text)
|
||||
* 统一过 g_clip;顶层(g_clip_n==0)= 全屏(g_xres×g_yres),故 IME/模态的全屏 scrim
|
||||
* 直绘不受裁剪。 */
|
||||
#define MUI_CLIP_MAX 16
|
||||
static int g_clip_stack[MUI_CLIP_MAX][4]; /* [x0,y0,x1,y1](闭开区间) */
|
||||
static int g_clip_n = 0;
|
||||
|
||||
static void clip_cur(int out[4]) { /* 当前 clip 边界(无 clip = 全屏) */
|
||||
if (g_clip_n > 0) {
|
||||
out[0] = g_clip_stack[g_clip_n - 1][0]; out[1] = g_clip_stack[g_clip_n - 1][1];
|
||||
out[2] = g_clip_stack[g_clip_n - 1][2]; out[3] = g_clip_stack[g_clip_n - 1][3];
|
||||
} else { out[0] = 0; out[1] = 0; out[2] = g_xres; out[3] = g_yres; }
|
||||
}
|
||||
static int clip_contains(int x, int y)
|
||||
{
|
||||
if (g_clip_n == 0) return x >= 0 && x < g_xres && y >= 0 && y < g_yres;
|
||||
return x >= g_clip_stack[g_clip_n - 1][0] && x < g_clip_stack[g_clip_n - 1][2] &&
|
||||
y >= g_clip_stack[g_clip_n - 1][1] && y < g_clip_stack[g_clip_n - 1][3];
|
||||
}
|
||||
|
||||
void meow_gfx_clip_push(int x, int y, int w, int h)
|
||||
{
|
||||
if (!g_init_ok || w <= 0 || h <= 0) return;
|
||||
int c[4]; clip_cur(c);
|
||||
int ix0 = x > c[0] ? x : c[0];
|
||||
int iy0 = y > c[1] ? y : c[1];
|
||||
int ix1 = (x + w) < c[2] ? (x + w) : c[2];
|
||||
int iy1 = (y + h) < c[3] ? (y + h) : c[3];
|
||||
if (ix1 < ix0) ix1 = ix0;
|
||||
if (iy1 < iy0) iy1 = iy0;
|
||||
if (g_clip_n >= MUI_CLIP_MAX) return; /* 栈满:忽略本次 push(保持当前 clip) */
|
||||
g_clip_stack[g_clip_n][0] = ix0; g_clip_stack[g_clip_n][1] = iy0;
|
||||
g_clip_stack[g_clip_n][2] = ix1; g_clip_stack[g_clip_n][3] = iy1;
|
||||
g_clip_n++;
|
||||
}
|
||||
void meow_gfx_clip_pop(void)
|
||||
{
|
||||
if (g_clip_n > 0) g_clip_n--;
|
||||
}
|
||||
|
||||
static char *g_dump_path = NULL;
|
||||
|
||||
/* ---- 状态栏「上收出屏只留提示线」(collapsed,基座)----
|
||||
@@ -158,6 +200,17 @@ static void dirty_add(int x, int y, int w, int h)
|
||||
if (x + w > g_xres) w = g_xres - x;
|
||||
if (y + h > g_yres) h = g_yres - y;
|
||||
if (w <= 0 || h <= 0) return;
|
||||
/* 绘制期裁剪:脏区也不越 clip(顶层 clip=全屏 → 无操作)。 */
|
||||
if (g_clip_n > 0) {
|
||||
int *c = g_clip_stack[g_clip_n - 1];
|
||||
int x1 = x + w, y1 = y + h;
|
||||
if (x < c[0]) x = c[0];
|
||||
if (y < c[1]) y = c[1];
|
||||
if (x1 > c[2]) x1 = c[2];
|
||||
if (y1 > c[3]) y1 = c[3];
|
||||
if (x1 <= x || y1 <= y) return;
|
||||
w = x1 - x; h = y1 - y;
|
||||
}
|
||||
for (int i = 0; i < g_ndirty; i++) {
|
||||
if (rect_hit(g_dirty[i][0], g_dirty[i][1], g_dirty[i][2], g_dirty[i][3], x, y, w, h)) {
|
||||
int nx1 = g_dirty[i][0] < x ? g_dirty[i][0] : x;
|
||||
@@ -237,6 +290,7 @@ void meow_gfx_blit_icon(int idx, int x, int y, int ink_h, uint32_t fg, int cy)
|
||||
for (int dx = 0; dx < t_w; dx++) {
|
||||
int tx = x0 + dx;
|
||||
if (tx < 0 || tx >= g_xres) continue;
|
||||
if (!clip_contains(tx, ty)) continue;
|
||||
int sx = minx + (dx * ink_w) / t_w;
|
||||
int a = src[sy * SB_ICON_SIZE + sx];
|
||||
if (a < 8) continue; /* 透明像素跳过 */
|
||||
@@ -265,7 +319,7 @@ static uint16_t px_read_rgb565(int x, int y)
|
||||
|
||||
static void put_px(int x, int y, uint32_t color)
|
||||
{
|
||||
if (x < 0 || x >= g_xres || y < 0 || y >= g_yres) return;
|
||||
if (!clip_contains(x, y)) return;
|
||||
if (g_bpp == 16) {
|
||||
px_write_rgb565(x, y, rgb565(color));
|
||||
} else {
|
||||
@@ -276,7 +330,7 @@ static void put_px(int x, int y, uint32_t color)
|
||||
|
||||
static void put_px_blend(int x, int y, uint32_t color, int alpha)
|
||||
{
|
||||
if (x < 0 || x >= g_xres || y < 0 || y >= g_yres) return;
|
||||
if (!clip_contains(x, y)) return;
|
||||
uint16_t fg = rgb565(color);
|
||||
if (g_bpp == 16) {
|
||||
uint16_t bg = px_read_rgb565(x, y);
|
||||
@@ -300,6 +354,10 @@ static void put_px_blend(int x, int y, uint32_t color, int alpha)
|
||||
void meow_ui_clear(uint32_t color)
|
||||
{
|
||||
if (!g_init_ok) return;
|
||||
if (g_clip_n > 0) { /* 绘制期裁剪:清当前 clip 区(顶层 clip=全屏 → 走快速整刷) */
|
||||
meow_ui_fill_rect(0, 0, g_xres, g_yres, color);
|
||||
return;
|
||||
}
|
||||
/* 快速整刷(16bit 用半字填充,可 memset 当色值由 32bit 拼接掩码) */
|
||||
if (g_bpp == 16) {
|
||||
uint16_t c16 = rgb565(color);
|
||||
@@ -327,6 +385,16 @@ void meow_ui_fill_rect(int x, int y, int w, int h, uint32_t color)
|
||||
if (x + w > g_xres) w = g_xres - x;
|
||||
if (y + h > g_yres) h = g_yres - y;
|
||||
if (w <= 0 || h <= 0) return;
|
||||
if (g_clip_n > 0) { /* 绘制期裁剪:与当前 clip 求交(顶层 clip=全屏 → 无操作) */
|
||||
int *c = g_clip_stack[g_clip_n - 1];
|
||||
int x1 = x + w, y1 = y + h;
|
||||
if (x < c[0]) x = c[0];
|
||||
if (y < c[1]) y = c[1];
|
||||
if (x1 > c[2]) x1 = c[2];
|
||||
if (y1 > c[3]) y1 = c[3];
|
||||
if (x1 <= x || y1 <= y) return;
|
||||
w = x1 - x; h = y1 - y;
|
||||
}
|
||||
if (g_bpp == 16) {
|
||||
uint16_t c16 = rgb565(color);
|
||||
for (int ry = y; ry < y + h; ry++) {
|
||||
@@ -534,6 +602,16 @@ void meow_ui_fill_rect_alpha(int x, int y, int w, int h, uint32_t color, int alp
|
||||
if (x + w > g_xres) w = g_xres - x;
|
||||
if (y + h > g_yres) h = g_yres - y;
|
||||
if (w <= 0 || h <= 0) return;
|
||||
if (g_clip_n > 0) { /* 绘制期裁剪:与当前 clip 求交(顶层 clip=全屏 → 无操作) */
|
||||
int *c = g_clip_stack[g_clip_n - 1];
|
||||
int x1 = x + w, y1 = y + h;
|
||||
if (x < c[0]) x = c[0];
|
||||
if (y < c[1]) y = c[1];
|
||||
if (x1 > c[2]) x1 = c[2];
|
||||
if (y1 > c[3]) y1 = c[3];
|
||||
if (x1 <= x || y1 <= y) return;
|
||||
w = x1 - x; h = y1 - y;
|
||||
}
|
||||
for (int ry = y; ry < y + h; ry++)
|
||||
for (int rx = x; rx < x + w; rx++) put_px_blend(rx, ry, color, alpha);
|
||||
dirty_add(x, y, w, h);
|
||||
@@ -677,13 +755,28 @@ static void text_draw(int x, int y, const char *s, int size, uint32_t color)
|
||||
{
|
||||
if (!g_init_ok || !s) return;
|
||||
if (g_mfont_ready && g_bpp == 16) {
|
||||
meow_font_drawtext((uint16_t *)g_fb, x, y, s, rgb565(color), size);
|
||||
int w = meow_font_width_text(s, size);
|
||||
int hh = meow_font_line_height(size);
|
||||
if (g_clip_n > 0) {
|
||||
int *c = g_clip_stack[g_clip_n - 1];
|
||||
if (x + w <= c[0] || x >= c[2] || y + hh <= c[1] || y >= c[3]) return; /* 与 clip 无交 */
|
||||
if (!(x >= c[0] && x + w <= c[2] && y >= c[1] && y + hh <= c[3])) {
|
||||
/* 部分相交:用「偏移 fb 子矩形 + 临时 fb 几何」做裁剪(meow_font 只按全屏剪)。
|
||||
* 把 fb 基址指向 clip 左上角、fb_w/h 设为 clip 尺寸、原点平移到 clip 坐标,
|
||||
* 这样 meow_font 的逐字形裁剪天然落在 clip 内;画完恢复全屏几何。 */
|
||||
uint16_t *fb = (uint16_t *)(g_fb + (size_t)c[1] * g_line + (size_t)c[0] * 2);
|
||||
meow_font_set_fb((unsigned)(c[2] - c[0]), (unsigned)(c[3] - c[1]), (unsigned)g_line);
|
||||
meow_font_drawtext(fb, x - c[0], y - c[1], s, rgb565(color), size);
|
||||
meow_font_set_fb((unsigned)g_xres, (unsigned)g_yres, (unsigned)g_line);
|
||||
dirty_add(x, y, w, hh);
|
||||
return;
|
||||
}
|
||||
}
|
||||
meow_font_drawtext((uint16_t *)g_fb, x, y, s, rgb565(color), size);
|
||||
dirty_add(x, y, w, hh);
|
||||
} else {
|
||||
int sc = fallback_scale(size);
|
||||
draw_text5x7(x, y, s, sc, color);
|
||||
draw_text5x7(x, y, s, sc, color); /* 走 put_px,自动过 clip */
|
||||
dirty_add(x, y, (int)strlen(s) * 6 * sc, 7 * sc);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user