Move text width calculation into draw_window_title to avoid double CSI stripping

Refactored so text_width_for_single_line is called inside draw_window_title
after CSI stripping, avoiding stripping the same text twice. The standalone
text_width_for_single_line wrapper is removed; draw_window_title now accepts
a size_t *actual_width output parameter that, when non-NULL, triggers text
width calculation and width reduction.

Agent-Logs-Url: https://github.com/kovidgoyal/kitty/sessions/a70cccb9-332a-4f7b-81f8-8cbeb7ed2c26

Co-authored-by: kovidgoyal <1308621+kovidgoyal@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-04-06 05:43:04 +00:00 committed by GitHub
parent 969562a999
commit 398fb8d156
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 20 additions and 29 deletions

View file

@ -1154,19 +1154,17 @@ apple_url_open_callback(const char* url) {
bool
draw_window_title(double font_sz_pts UNUSED, double ydpi UNUSED, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height) {
draw_window_title(double font_sz_pts UNUSED, double ydpi UNUSED, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height, size_t *actual_width) {
static char buf[2048];
strip_csi_(text, buf, arraysz(buf));
if (actual_width) {
size_t text_w = cocoa_text_width_for_single_line(buf, height);
if (text_w > 0 && text_w < width) width = text_w;
*actual_width = width;
}
return cocoa_render_line_of_text(buf, fg, bg, output_buf, width, height);
}
size_t
text_width_for_single_line(double font_sz_pts UNUSED, double ydpi UNUSED, const char *text, size_t height) {
static char buf[2048];
strip_csi_(text, buf, arraysz(buf));
return cocoa_text_width_for_single_line(buf, height);
}
uint8_t*
draw_single_ascii_char(const char ch, size_t *result_width, size_t *result_height) {
@ -1211,13 +1209,18 @@ draw_text_callback(GLFWwindow *window, const char *text, uint32_t fg, uint32_t b
}
bool
draw_window_title(double font_sz_pts, double ydpi, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height) {
draw_window_title(double font_sz_pts, double ydpi, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height, size_t *actual_width) {
FreeTypeRenderCtx ctx;
if (!(ctx = freetype_render_ctx(false))) return false;
static char buf[2048];
strip_csi_(text, buf, arraysz(buf));
unsigned px_sz = (unsigned)(font_sz_pts * ydpi / 72.);
px_sz = MIN(px_sz, 3 * height / 4);
if (actual_width) {
size_t text_w = freetype_text_width_for_single_line(ctx, buf, px_sz);
if (text_w > 0 && text_w < width) width = text_w;
*actual_width = width;
}
#define RGB2BGR(x) (x & 0xFF000000) | ((x & 0xFF0000) >> 16) | (x & 0x00FF00) | ((x & 0x0000FF) << 16)
bool ok = render_single_line(ctx, buf, px_sz, RGB2BGR(fg), RGB2BGR(bg), output_buf, width, height, 0, 0, 0, false);
#undef RGB2BGR
@ -1225,17 +1228,6 @@ draw_window_title(double font_sz_pts, double ydpi, const char *text, color_type
return ok;
}
size_t
text_width_for_single_line(double font_sz_pts, double ydpi, const char *text, size_t height) {
FreeTypeRenderCtx ctx;
if (!(ctx = freetype_render_ctx(false))) return 0;
static char buf[2048];
strip_csi_(text, buf, arraysz(buf));
unsigned px_sz = (unsigned)(font_sz_pts * ydpi / 72.);
px_sz = MIN(px_sz, 3 * height / 4);
return freetype_text_width_for_single_line(ctx, buf, px_sz);
}
uint8_t*
draw_single_ascii_char(const char ch, size_t *result_width, size_t *result_height) {
FreeTypeRenderCtx ctx;
@ -3109,17 +3101,17 @@ draw_single_line_of_text(PyObject *self UNUSED, PyObject *args) {
double font_sz_pts = w->fonts_data->font_sz_in_pts;
double ydpi = w->fonts_data->logical_dpi_y;
size_t height = (size_t)w->fonts_data->fcm.cell_height + padding_y;
if (max_width) {
size_t text_w = text_width_for_single_line(font_sz_pts, ydpi, text, height);
if (text_w > 0 && text_w < (size_t)width) width = (int)text_w;
}
size_t buf_sz = (size_t)width * height * 4;
RAII_PyObject(ans, PyBytes_FromStringAndSize(NULL, buf_sz)); if (!ans) return NULL;
if (!draw_window_title(font_sz_pts, ydpi, text, fg, bg, (uint8_t*)PyBytes_AS_STRING(ans), width, height)) {
size_t actual_width = width;
if (!draw_window_title(font_sz_pts, ydpi, text, fg, bg, (uint8_t*)PyBytes_AS_STRING(ans), width, height, max_width ? &actual_width : NULL)) {
if (!PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "Failed to render text");
return NULL;
}
return Py_BuildValue("Oi", ans, width);
if (actual_width < (size_t)width) {
if (_PyBytes_Resize(&ans, actual_width * height * 4) < 0) return NULL;
}
return Py_BuildValue("Oi", ans, (int)actual_width);
}
static bool

View file

@ -845,7 +845,7 @@ render_a_bar(const UIRenderData *ui, WindowBarData *bar, PyObject *title, bool a
static char titlebuf[2048] = {0};
if (!title) return 0;
snprintf(titlebuf, arraysz(titlebuf), " %s", PyUnicode_AsUTF8(title));
if (!draw_window_title(ui->os_window->fonts_data->font_sz_in_pts, ui->os_window->fonts_data->logical_dpi_y, titlebuf, fg, bg, bar->buf, bar_width, bar_height)) return 0;
if (!draw_window_title(ui->os_window->fonts_data->font_sz_in_pts, ui->os_window->fonts_data->logical_dpi_y, titlebuf, fg, bg, bar->buf, bar_width, bar_height, NULL)) return 0;
Py_CLEAR(bar->last_drawn_title_object_id);
bar->last_drawn_title_object_id = Py_NewRef(title);
}

View file

@ -572,8 +572,7 @@ const char* format_mods(unsigned mods);
void dispatch_pending_clicks(id_type, void*);
void send_pending_click_to_window(Window*, int);
void get_platform_dependent_config_values(void *glfw_window);
bool draw_window_title(double, double, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height);
size_t text_width_for_single_line(double font_sz_pts, double ydpi, const char *text, size_t height);
bool draw_window_title(double, double, const char *text, color_type fg, color_type bg, uint8_t *output_buf, size_t width, size_t height, size_t *actual_width);
uint8_t* draw_single_ascii_char(const char ch, size_t *result_width, size_t *result_height);
bool is_os_window_fullscreen(OSWindow *);
void update_ime_focus(OSWindow* osw, bool focused);