Fix bg_alpha opacity and wide char truncation in freetype_render_ui_text.c

1. Fix alpha_blend_premult to compute result alpha as
   over_alpha + (1 - over_alpha/255) * under_alpha instead of
   just using the under (background) alpha. This fixes the DnD drag
   image where bg_alpha was incorrectly making the entire image
   semi-transparent (including fully-opaque text pixels), because text
   pixels were inheriting the background pixel's alpha value.

2. Fix truncation check in render_run from >= to > so that characters
   whose cursor advance exactly equals the available output width are
   not wrongly treated as truncating. This fixes wide characters like
   笔 and NERD font symbols being rendered as '...' (ellipsis) when
   draw_window_title shrinks the render width to the computed text
   width via freetype_text_width_for_single_line.

Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/6ca5e045-57ab-4fba-bff5-fa4dece3131f

Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-05-05 06:01:40 +00:00 committed by GitHub
parent c690a3f3e8
commit 313561d282
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -189,9 +189,11 @@ static pixel
alpha_blend_premult(pixel over, pixel under) {
const uint16_t over_r = (over >> 16) & 0xff, over_g = (over >> 8) & 0xff, over_b = over & 0xff;
const uint16_t under_r = (under >> 16) & 0xff, under_g = (under >> 8) & 0xff, under_b = under & 0xff;
const uint16_t factor = 255 - ((over >> 24) & 0xff);
const uint16_t over_alpha = (over >> 24) & 0xff;
const uint16_t factor = 255 - over_alpha;
const uint16_t result_alpha = over_alpha + (uint16_t)(factor * ((under >> 24) & 0xff) / 255);
#define ans(x) (over_##x + (factor * under_##x) / 255)
return ARGB(under >> 24, ans(r), ans(g), ans(b));
return ARGB(result_alpha, ans(r), ans(g), ans(b));
#undef ans
}
@ -316,7 +318,7 @@ render_run(RenderCtx *ctx, RenderState *rs) {
unsigned int limit = len;
for (unsigned int i = 0; i < len; i++) {
float delta = (float)positions[i].x_offset / 64.0f + (float)positions[i].x_advance / 64.0f;
if (pos + delta >= rs->output_width) {
if (pos + delta > rs->output_width) {
limit = i;
break;
}