opt: avoid invalid decorate draw

This commit is contained in:
DreamMaoMao 2026-06-24 17:50:18 +08:00
parent 5639b0728a
commit d4907d63af

View file

@ -182,6 +182,10 @@ static void get_text_pixel_size(MangoJumpLabel *node, const char *text,
static void draw_rounded_rect(cairo_t *cr, double x, double y, double w, static void draw_rounded_rect(cairo_t *cr, double x, double y, double w,
double h, double r) { double h, double r) {
// 宽高非正时不绘制任何东西
if (w <= 0.0 || h <= 0.0)
return;
double degrees = G_PI / 180.0; double degrees = G_PI / 180.0;
cairo_new_sub_path(cr); cairo_new_sub_path(cr);
cairo_arc(cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees); cairo_arc(cr, x + w - r, y + r, r, -90 * degrees, 0 * degrees);
@ -198,7 +202,7 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
if (scale <= 0.0f) if (scale <= 0.0f)
scale = 1.0f; scale = 1.0f;
/* 脏检查,加入 focused 状态 */ // 脏检查
if (node->cached_scale == scale && node->cached_font_desc && if (node->cached_scale == scale && node->cached_font_desc &&
strcmp(node->cached_font_desc, node->font_desc) == 0 && strcmp(node->cached_font_desc, node->font_desc) == 0 &&
node->cached_text && strcmp(node->cached_text, text) == 0 && node->cached_text && strcmp(node->cached_text, text) == 0 &&
@ -220,7 +224,7 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
return; return;
} }
/* 更新缓存 */ // 更新缓存
g_free(node->cached_text); g_free(node->cached_text);
node->cached_text = g_strdup(text); node->cached_text = g_strdup(text);
g_free(node->cached_font_desc); g_free(node->cached_font_desc);
@ -264,6 +268,7 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
int32_t box_logical_w = logical_text_w + 2 * node->padding_x; int32_t box_logical_w = logical_text_w + 2 * node->padding_x;
int32_t box_logical_h = logical_text_h + 2 * node->padding_y; int32_t box_logical_h = logical_text_h + 2 * node->padding_y;
// 物理像素尺寸包含边框,避免边框越界
int32_t required_pixel_w = int32_t required_pixel_w =
(int32_t)((box_logical_w + 2 * node->border_width) * scale + 0.5f); (int32_t)((box_logical_w + 2 * node->border_width) * scale + 0.5f);
int32_t required_pixel_h = int32_t required_pixel_h =
@ -316,13 +321,15 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
radius = bg_w / 2.0; radius = bg_w / 2.0;
if (radius > bg_h / 2.0) if (radius > bg_h / 2.0)
radius = bg_h / 2.0; radius = bg_h / 2.0;
if (radius < 0.0)
radius = 0.0;
const float *active_bg = const float *active_bg =
node->focused ? node->focus_bg_color : node->bg_color; node->focused ? node->focus_bg_color : node->bg_color;
const float *active_fg = const float *active_fg =
node->focused ? node->focus_fg_color : node->fg_color; node->focused ? node->focus_fg_color : node->fg_color;
bool draw_bg = (active_bg[3] > 0.0f); // 使用 active_bg bool draw_bg = (active_bg[3] > 0.0f) && (bg_w > 0.0 && bg_h > 0.0);
bool draw_border = bool draw_border =
(node->border_width > 0) && (node->border_color[3] > 0.0f); (node->border_width > 0) && (node->border_color[3] > 0.0f);
@ -338,6 +345,8 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
} }
} }
// 文本绘制仅在背景区域有有效空间时进行
if (bg_w > 0.0 && bg_h > 0.0) {
cairo_save(cr); cairo_save(cr);
double text_x = (node->border_width + node->padding_x) * scale; double text_x = (node->border_width + node->padding_x) * scale;
double text_y = (node->border_width + node->padding_y) * scale; double text_y = (node->border_width + node->padding_y) * scale;
@ -357,6 +366,7 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
g_object_unref(layout); g_object_unref(layout);
g_object_unref(ctx); g_object_unref(ctx);
cairo_restore(cr); cairo_restore(cr);
}
if (draw_border) { if (draw_border) {
cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1], cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1],
@ -369,6 +379,25 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
double bw = bg_w + border; double bw = bg_w + border;
double bh = bg_h + border; double bh = bg_h + border;
// 确保边框矩形不越界且宽高为正
if (bx < 0.0) {
bw += bx; // bx 为负bw 缩小
bx = 0.0;
}
if (by < 0.0) {
bh += by;
by = 0.0;
}
if (bx + bw > (double)node->surface_pixel_w)
bw = (double)node->surface_pixel_w - bx;
if (by + bh > (double)node->surface_pixel_h)
bh = (double)node->surface_pixel_h - by;
if (bw < 0.0)
bw = 0.0;
if (bh < 0.0)
bh = 0.0;
if (bw > 0.0 && bh > 0.0) {
if (radius > 0.0) { if (radius > 0.0) {
double outer_radius = radius + half_lw; double outer_radius = radius + half_lw;
if (outer_radius < 0.0) if (outer_radius < 0.0)
@ -379,6 +408,7 @@ void mango_jump_label_node_update(MangoJumpLabel *node, const char *text,
} }
cairo_stroke(cr); cairo_stroke(cr);
} }
}
cairo_surface_flush(node->surface); cairo_surface_flush(node->surface);
cairo_destroy(cr); cairo_destroy(cr);
@ -409,7 +439,6 @@ void mango_jump_label_node_set_focus(MangoJumpLabel *node, bool focused) {
if (!node || node->focused == focused) if (!node || node->focused == focused)
return; return;
node->focused = focused; node->focused = focused;
// 使用缓存的文本和缩放触发重绘(如果无文本则不重绘)
if (node->cached_text && node->cached_scale > 0.0f) { if (node->cached_text && node->cached_scale > 0.0f) {
mango_jump_label_node_update(node, node->cached_text, mango_jump_label_node_update(node, node->cached_text,
node->cached_scale); node->cached_scale);
@ -537,7 +566,7 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
node->last_text = safe_text; // 所有权转移 node->last_text = safe_text; // 所有权转移
node->last_scale = scale; node->last_scale = scale;
// 脏检查加入 focused // 脏检查
if (node->cached_scale == scale && node->cached_font_desc && if (node->cached_scale == scale && node->cached_font_desc &&
strcmp(node->cached_font_desc, node->font_desc) == 0 && strcmp(node->cached_font_desc, node->font_desc) == 0 &&
node->cached_text && strcmp(node->cached_text, safe_text) == 0 && node->cached_text && strcmp(node->cached_text, safe_text) == 0 &&
@ -607,8 +636,18 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
if (box_logical_h < 0) if (box_logical_h < 0)
box_logical_h = 0; box_logical_h = 0;
// surface 物理尺寸包含边框,避免边框绘制越界
int32_t required_pixel_w = (int32_t)(node->target_width * scale + 0.5f); int32_t required_pixel_w = (int32_t)(node->target_width * scale + 0.5f);
int32_t required_pixel_h = (int32_t)(node->target_height * scale + 0.5f); int32_t required_pixel_h = (int32_t)(node->target_height * scale + 0.5f);
// 如果边框会伸出 target 区域,则扩展 surface 尺寸以完全容纳
double border_phys = node->border_width * scale;
if (border_phys > 0.0) {
// 边框描边会向外延伸 half line width所以需要额外空间
int extra_w = (int32_t)ceil(border_phys * 0.5);
int extra_h = (int32_t)ceil(border_phys * 0.5);
required_pixel_w += extra_w;
required_pixel_h += extra_h;
}
if (required_pixel_w < 1) if (required_pixel_w < 1)
required_pixel_w = 1; required_pixel_w = 1;
if (required_pixel_h < 1) if (required_pixel_h < 1)
@ -640,7 +679,6 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
cairo_paint(cr); cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER); cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
double border_phys = node->border_width * scale;
double bg_x = border_phys; double bg_x = border_phys;
double bg_y = border_phys; double bg_y = border_phys;
double bg_w = box_logical_w * scale; double bg_w = box_logical_w * scale;
@ -656,13 +694,15 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
radius = bg_w / 2.0; radius = bg_w / 2.0;
if (radius > bg_h / 2.0) if (radius > bg_h / 2.0)
radius = bg_h / 2.0; radius = bg_h / 2.0;
if (radius < 0.0)
radius = 0.0;
const float *active_bg = const float *active_bg =
node->focused ? node->focus_bg_color : node->bg_color; node->focused ? node->focus_bg_color : node->bg_color;
const float *active_fg = const float *active_fg =
node->focused ? node->focus_fg_color : node->fg_color; node->focused ? node->focus_fg_color : node->fg_color;
bool draw_bg = (active_bg[3] > 0.0f); bool draw_bg = (active_bg[3] > 0.0f) && (bg_w > 0.0 && bg_h > 0.0);
bool draw_border = bool draw_border =
(node->border_width > 0) && (node->border_color[3] > 0.0f); (node->border_width > 0) && (node->border_color[3] > 0.0f);
@ -678,6 +718,8 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
} }
} }
// 仅在背景区域有空间时进行
if (bg_w > 0.0 && bg_h > 0.0) {
int32_t text_area_logical_w = box_logical_w - 2 * node->padding_x; int32_t text_area_logical_w = box_logical_w - 2 * node->padding_x;
int32_t text_area_logical_h = box_logical_h - 2 * node->padding_y; int32_t text_area_logical_h = box_logical_h - 2 * node->padding_y;
if (text_area_logical_w > 0 && text_area_logical_h > 0) { if (text_area_logical_w > 0 && text_area_logical_h > 0) {
@ -716,6 +758,7 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
g_object_unref(ctx); g_object_unref(ctx);
cairo_restore(cr); cairo_restore(cr);
} }
}
if (draw_border) { if (draw_border) {
cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1], cairo_set_source_rgba(cr, node->border_color[0], node->border_color[1],
@ -728,6 +771,25 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
double bw = bg_w + border_phys; double bw = bg_w + border_phys;
double bh = bg_h + border_phys; double bh = bg_h + border_phys;
// 确保边框矩形不越界且宽高为正
if (bx < 0.0) {
bw += bx;
bx = 0.0;
}
if (by < 0.0) {
bh += by;
by = 0.0;
}
if (bx + bw > (double)node->surface_pixel_w)
bw = (double)node->surface_pixel_w - bx;
if (by + bh > (double)node->surface_pixel_h)
bh = (double)node->surface_pixel_h - by;
if (bw < 0.0)
bw = 0.0;
if (bh < 0.0)
bh = 0.0;
if (bw > 0.0 && bh > 0.0) {
if (radius > 0.0) { if (radius > 0.0) {
double outer_radius = radius + half_lw; double outer_radius = radius + half_lw;
if (outer_radius < 0.0) if (outer_radius < 0.0)
@ -738,6 +800,7 @@ void mango_group_bar_update(MangoGroupBar *node, const char *text,
} }
cairo_stroke(cr); cairo_stroke(cr);
} }
}
cairo_surface_flush(node->surface); cairo_surface_flush(node->surface);
cairo_destroy(cr); cairo_destroy(cr);