Files
MeowOS-For-R3P2/patch_v2/sdk/meow_ui_draw.c
T

358 lines
12 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* meow_ui_draw.c — 绘制物注册表 / z 序 / 区域重画(§6.2 / SDK_Z_ORDER_DESIGN §2)。
*
* 非保留模型下,把「清底 + 按 z 重画重叠区完整 z 栈」下沉到 SDK:
* - 控件(meow_widget)创建即自动注册(create 末尾调 meow_draw_widget_register),
* meow_widget_free 自动注销;rect 实时读 w->x/y/w/h;
* - App 直绘的非控件内容显式 meow_draw_custom_register(声明 bbox + 绘制回调);
* - z 自动推导(子>父、同层注册先序);显式 set_z 粘滞、置顶。
* 显式 z 存于本注册表(按 w 反查 entry),**不改 struct meow_widget**(零 ABI 破坏)。
*/
#include "meow_ui.h"
#include "meow_ui_internal.h"
#include "meow_ui_view.h"
#include <stdlib.h>
#include <string.h>
#define MEOW_DRAW_MAX 256
#define MEOW_ITEM_VIEW 2 /* 内部 kinds(不进公共枚举):meow_view 绘制物 */
typedef struct draw_entry {
int kind; /* MEOW_ITEM_WIDGET / MEOW_ITEM_CUSTOM / MEOW_ITEM_VIEW */
meow_widget *w; /* WIDGET:绘制其 meow_widget_draw(w) */
meow_draw_fn draw_cb; /* CUSTOM:绘制回调 */
void *ctx; /* CUSTOM: 传给 draw_cb; VIEW: (meow_view*)v */
int rx, ry, rw, rh; /* CUSTOM bbox(WIDGET 读 w->x/y/w/h,VIEW 读 v->x/y/w/h) */
int z; /* 生效 z(显式=其值,否则=自动推导) */
int z_explicit; /* 1=显式(粘滞) */
int id; /* CUSTOM id(0=无效) */
int seq; /* 全局注册序(z 同值时稳定先序) */
struct meow_view *view; /* WIDGET:所属 view(z 深度源)+1 */
} draw_entry;
static draw_entry g_e[MEOW_DRAW_MAX];
static int g_n = 0;
static int g_seq = 0; /* 全局注册序(单调递增) */
static int g_next_id = 1; /* CUSTOM id 起点(0=无效) */
static uint32_t g_page_bg = 0;
static int g_page_bg_set = 0;
/* ---- 内部访问器(widget.c 提供;跨 TU 用 meow_ui_internal.h 声明)---- */
static int w_is_layout(const meow_widget *w) { return meow_widget_is_layout(w); }
/* ---- 查找 ---- */
static draw_entry *e_find_widget(const meow_widget *w)
{
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_WIDGET && g_e[i].w == w) return &g_e[i];
return NULL;
}
static draw_entry *e_find_view(const meow_view *v)
{
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_VIEW && g_e[i].ctx == (void *)v) return &g_e[i];
return NULL;
}
static draw_entry *e_find_id(int id)
{
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_CUSTOM && g_e[i].id == id) return &g_e[i];
return NULL;
}
/* ---- 深度:view 树深度 ---- */
static int view_depth(const meow_view *v)
{
int d = 0;
const meow_view *p = v ? v->parent : NULL;
while (p) {
d++;
if (d > MEOW_Z_DEPTH_MAX) break;
p = p->parent;
}
return d;
}
/* ---- 深度:widget 所属嵌套深度(view 树为主;否则 W_LAYOUT children 反推;否则 0)---- */
static int widget_nest_depth(meow_widget *w, int depth)
{
if (depth > MEOW_Z_DEPTH_MAX) return MEOW_Z_DEPTH_MAX;
draw_entry *e = e_find_widget(w);
if (e && e->view) return view_depth(e->view) + 1; /* 视图树深度源(更确定) */
/* 注册表反推:w 是否经 meow_layout_add 挂在某布局下(此时布局自身已注册为 WIDGET)。 */
for (int i = 0; i < g_n; i++) {
if (g_e[i].kind != MEOW_ITEM_WIDGET) continue;
meow_widget *lw = g_e[i].w;
if (!lw || !w_is_layout(lw)) continue;
int nc = meow_widget_nchild(lw);
for (int j = 0; j < nc; j++)
if (meow_widget_child_at(lw, j) == w)
return widget_nest_depth(lw, depth + 1) + 1; /* 子层 >= 父层+1 */
}
return 0;
}
/* 计算 auto z(显式不重算——粘滞):depth*STRIDE + 层内 seq(注册先序,折叠 MEOW_Z_PER_LEVEL_MAX)。 */
static void e_compute_auto(draw_entry *e)
{
if (e->z_explicit) return;
int depth = 0;
if (e->kind == MEOW_ITEM_WIDGET && e->w) depth = widget_nest_depth(e->w, 0);
else if (e->kind == MEOW_ITEM_VIEW && e->ctx) depth = view_depth((const meow_view *)e->ctx);
/* CUSTOM:z 恒显式(register 传入),不进 auto 分支 */
int cnt = 0;
for (int i = 0; i < g_n; i++) {
draw_entry *o = &g_e[i];
if (o == e || o->z_explicit) continue;
if (o->seq >= e->seq) continue;
if (o->z / MEOW_Z_STRIDE == depth) cnt++;
}
if (cnt > MEOW_Z_PER_LEVEL_MAX) cnt = MEOW_Z_PER_LEVEL_MAX;
e->z = depth * MEOW_Z_STRIDE + cnt;
}
/* ============================================================ */
/* 控件自动注册 / 注销(create 末尾 / meow_widget_free 调用) */
/* ============================================================ */
void meow_draw_widget_register(meow_widget *w)
{
if (!w || e_find_widget(w)) return; /* 幂等 */
if (g_n >= MEOW_DRAW_MAX) return; /* 满:静默(骨架级) */
draw_entry *e = &g_e[g_n++];
memset(e, 0, sizeof *e);
e->kind = MEOW_ITEM_WIDGET;
e->w = w;
e->seq = g_seq++;
e_compute_auto(e);
}
void meow_draw_widget_unregister(meow_widget *w)
{
if (!w) return;
int idx = -1;
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_WIDGET && g_e[i].w == w) { idx = i; break; }
if (idx < 0) return;
g_e[idx] = g_e[--g_n]; /* 交换移除(seq 保留,排序稳定) */
}
int meow_draw_widget_registered(const meow_widget *w)
{
return w ? e_find_widget(w) != NULL : 0;
}
void meow_draw_widget_set_view(meow_widget *w, struct meow_view *v)
{
draw_entry *e = e_find_widget(w);
if (!e) return;
e->view = v;
e_compute_auto(e);
}
/* ============================================================ */
/* 显式 z(widget) */
/* ============================================================ */
void meow_widget_set_z(meow_widget *w, int z)
{
if (!w || z < 0) return;
draw_entry *e = e_find_widget(w);
if (!e) return;
e->z_explicit = 1;
e->z = z;
}
int meow_widget_z(const meow_widget *w)
{
if (!w) return 0;
draw_entry *e = e_find_widget((meow_widget *)w);
if (!e) return 0;
if (e->z_explicit) return e->z;
e_compute_auto(e);
return e->z;
}
void meow_widget_clear_z(meow_widget *w)
{
if (!w) return;
draw_entry *e = e_find_widget(w);
if (!e) return;
e->z_explicit = 0;
e_compute_auto(e);
}
/* ============================================================ */
/* CUSTOM(App 直绘)注册 / 注销 / 改 z */
/* ============================================================ */
int meow_draw_custom_register(int z, int x, int y, int w, int h,
meow_draw_fn cb, void *ctx)
{
if (!cb || w <= 0 || h <= 0) return 0;
if (g_n >= MEOW_DRAW_MAX) return 0;
draw_entry *e = &g_e[g_n++];
memset(e, 0, sizeof *e);
e->kind = MEOW_ITEM_CUSTOM;
e->draw_cb = cb;
e->ctx = ctx;
e->rx = x; e->ry = y; e->rw = w; e->rh = h;
e->z = z < 0 ? 0 : z;
e->z_explicit = 1;
e->id = g_next_id++;
e->seq = g_seq++;
return e->id;
}
void meow_draw_unregister(int id)
{
if (id <= 0) return;
int idx = -1;
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_CUSTOM && g_e[i].id == id) { idx = i; break; }
if (idx < 0) return;
g_e[idx] = g_e[--g_n];
}
int meow_draw_set_z(int id, int z)
{
if (id <= 0 || z < 0) return -1;
draw_entry *e = e_find_id(id);
if (!e) return -1;
e->z = z;
e->z_explicit = 1;
return 0;
}
/* ============================================================ */
/* view 绘制物注册 / 注销 */
/* ============================================================ */
void meow_draw_view_register(struct meow_view *v)
{
if (!v || e_find_view(v)) return;
if (g_n >= MEOW_DRAW_MAX) return;
draw_entry *e = &g_e[g_n++];
memset(e, 0, sizeof *e);
e->kind = MEOW_ITEM_VIEW;
e->ctx = (void *)v;
e->seq = g_seq++;
e_compute_auto(e);
}
void meow_draw_view_unregister(struct meow_view *v)
{
if (!v) return;
int idx = -1;
for (int i = 0; i < g_n; i++)
if (g_e[i].kind == MEOW_ITEM_VIEW && g_e[i].ctx == (void *)v) { idx = i; break; }
if (idx < 0) return;
g_e[idx] = g_e[--g_n];
}
int meow_draw_view_entered(const struct meow_view *v)
{
return v ? meow_view_get_state(v) & MEOW_VIEW_STATE_ENTERED : 0;
}
void meow_draw_view_set_z(struct meow_view *v, int z)
{
draw_entry *e = e_find_view(v);
if (!e) return;
if (z <= 0) {
e->z_explicit = 0;
e_compute_auto(e);
} else {
e->z_explicit = 1;
e->z = z;
}
}
/* ============================================================ */
/* page bg / 区域重画 / 整帧 */
/* ============================================================ */
void meow_ui_set_page_bg(uint32_t color) { g_page_bg = color; g_page_bg_set = 1; }
uint32_t meow_ui_page_bg(void) { return g_page_bg_set ? g_page_bg : meow_theme_get()->bg; }
static int rect_hit(int ax, int ay, int aw, int ah, int bx, int by, int bw, int bh)
{
return ax < bx + bw && ax + aw > bx && ay < by + bh && ay + ah > by;
}
static int entry_rect(draw_entry *e, int out[4])
{
if (e->kind == MEOW_ITEM_WIDGET && e->w) {
meow_widget_rect(e->w, out);
} else if (e->kind == MEOW_ITEM_VIEW && e->ctx) {
meow_view *v = (meow_view *)e->ctx;
out[0] = v->x; out[1] = v->y; out[2] = v->w; out[3] = v->h;
} else {
out[0] = e->rx; out[1] = e->ry; out[2] = e->rw; out[3] = e->rh;
}
return out[2] > 0 && out[3] > 0;
}
static void draw_one(draw_entry *e)
{
switch (e->kind) {
case MEOW_ITEM_WIDGET:
meow_widget_draw(e->w);
break;
case MEOW_ITEM_CUSTOM:
e->draw_cb(e->ctx);
break;
case MEOW_ITEM_VIEW: {
meow_view *v = (meow_view *)e->ctx;
if (v->hooks.on_draw) v->hooks.on_draw(v, meow_theme_get(), v->ctx);
break;
}
default:
break;
}
}
static void paint(int full, int x, int y, int w, int h)
{
uint32_t bg = meow_ui_page_bg();
if (full) {
meow_ui_clear(bg);
} else {
if (w <= 0 || h <= 0) return;
meow_ui_fill_rect(x, y, w, h, bg);
}
/* 刷新 auto z + 组装按 (z,seq) 升序的绘制序(owner==active 过滤 WIDGET;view 须已进入)。 */
draw_entry *order[MEOW_DRAW_MAX];
int nn = 0;
int active = meow_ui_activity_active();
for (int i = 0; i < g_n; i++) {
draw_entry *e = &g_e[i];
e_compute_auto(e);
if (e->kind == MEOW_ITEM_WIDGET && e->w && meow_widget_owner(e->w) != active) continue;
if (e->kind == MEOW_ITEM_VIEW && !meow_draw_view_entered((meow_view *)e->ctx)) continue;
order[nn++] = e;
}
/* 稳定插入排序:(z 升序,同 z 按 seq 升序=注册先序)。 */
for (int i = 1; i < nn; i++) {
draw_entry *key = order[i];
int j = i - 1;
while (j >= 0 && (order[j]->z > key->z ||
(order[j]->z == key->z && order[j]->seq > key->seq))) {
order[j + 1] = order[j];
j--;
}
order[j + 1] = key;
}
if (full) {
for (int i = 0; i < nn; i++) draw_one(order[i]);
meow_ui_flush();
} else {
int r[4];
for (int i = 0; i < nn; i++) {
if (!entry_rect(order[i], r)) continue;
if (rect_hit(r[0], r[1], r[2], r[3], x, y, w, h)) draw_one(order[i]);
}
meow_ui_flush_region(x, y, w, h);
}
}
void meow_ui_invalidate(int x, int y, int w, int h)
{
if (w <= 0 || h <= 0) return;
paint(0, x, y, w, h);
}
void meow_ui_paint_full(void)
{
paint(1, 0, 0, 0, 0);
}