From 9d4818e58b16272c655034a9745dc65c8de79513 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sat, 26 Oct 2024 13:52:00 +0530 Subject: [PATCH] Speed up unicode_in_range --- kitty/line.c | 22 ++++++---------------- kitty/line.h | 8 ++++++++ kitty/text-cache.c | 13 +++++++++++++ kitty/text-cache.h | 1 + 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/kitty/line.c b/kitty/line.c index 1bebc7a78..2c7d66d5e 100644 --- a/kitty/line.c +++ b/kitty/line.c @@ -225,17 +225,6 @@ text_at(Line* self, Py_ssize_t xval) { return cell_text(self->cpu_cells + xval, self->text_cache); } -static size_t -cell_as_unicode(ListOfChars *lc, bool include_cc, Py_UCS4 *buf, char_type zero_char) { - size_t n = 1; - buf[0] = lc->chars[0] ? lc->chars[0] : zero_char; - if (include_cc && lc->count > 1) { - memcpy(buf + 1, lc->chars + 1, (lc->count - 1) * sizeof(lc->chars[0])); - n += lc->count - 1; - } - return n; -} - size_t cell_as_unicode_for_fallback(const ListOfChars *lc, Py_UCS4 *buf) { size_t n = 1; @@ -271,15 +260,16 @@ PyObject* unicode_in_range(const Line *self, const index_type start, const index_type limit, const bool include_cc, const bool add_trailing_newline, const bool skip_zero_cells) { size_t n = 0; static Py_UCS4 buf[4096]; - RAII_ListOfChars(lc); + ListOfChars lc; char_type previous_width = 0; - for(index_type i = start; i < limit; i++) { - text_in_cell(self->cpu_cells + i, self->text_cache, &lc); + for (index_type i = start; i < limit; i++) { + lc.chars = buf + n; lc.capacity = arraysz(buf) - n; + if (!text_in_cell_without_alloc(self->cpu_cells + i, self->text_cache, &lc)) break; if (!lc.chars[0]) { if (previous_width == 2) { previous_width = 0; continue; }; if (skip_zero_cells) continue; + lc.chars[0] = ' '; } - if (lc.count + n >= arraysz(buf)) break; if (lc.chars[0] == '\t') { buf[n++] = '\t'; unsigned num_cells_to_skip_for_tab = lc.count > 1 ? lc.chars[1] : 0; @@ -288,7 +278,7 @@ unicode_in_range(const Line *self, const index_type start, const index_type limi num_cells_to_skip_for_tab--; } } else { - n += cell_as_unicode(&lc, include_cc, buf + n, ' '); + n += include_cc ? lc.count : 1; } previous_width = self->gpu_cells[i].attrs.width; } diff --git a/kitty/line.h b/kitty/line.h index f1651521d..ec77c8be3 100644 --- a/kitty/line.h +++ b/kitty/line.h @@ -92,6 +92,14 @@ text_in_cell(const CPUCell *c, const TextCache *tc, ListOfChars *ans) { } } +static inline bool +text_in_cell_without_alloc(const CPUCell *c, const TextCache *tc, ListOfChars *ans) { + if (c->ch_is_idx) return tc_chars_at_index_without_alloc(tc, c->ch_or_idx, ans); + ans->count = 1; + ans->chars[0] = c->ch_or_idx; + return true; +} + static inline void cell_set_chars(CPUCell *c, TextCache *tc, const ListOfChars *lc) { if (lc->count <= 1) cell_set_char(c, lc->chars[0]); diff --git a/kitty/text-cache.c b/kitty/text-cache.c index 7e34ea656..fea92d273 100644 --- a/kitty/text-cache.c +++ b/kitty/text-cache.c @@ -87,6 +87,19 @@ tc_chars_at_index(const TextCache *self, char_type idx, ListOfChars *ans) { } } +bool +tc_chars_at_index_without_alloc(const TextCache *self, char_type idx, ListOfChars *ans) { + if (self->array.count > idx) { + ans->count = self->array.items[idx].count; + if (ans->capacity < ans->count) return false; + memcpy(ans->chars, self->array.items[idx].chars, sizeof(ans->chars[0]) * ans->count); + } else { + ans->count = 0; + } + return true; +} + + unsigned tc_num_codepoints(const TextCache *self, char_type idx) { return self->array.count > idx ? self->array.items[idx].count : 0; diff --git a/kitty/text-cache.h b/kitty/text-cache.h index ae609410c..a9f336ad4 100644 --- a/kitty/text-cache.h +++ b/kitty/text-cache.h @@ -53,4 +53,5 @@ void tc_chars_at_index(const TextCache *self, char_type idx, ListOfChars *ans); unsigned tc_chars_at_index_ansi(const TextCache *self, char_type idx, ANSIBuf *output); char_type tc_get_or_insert_chars(TextCache *self, const ListOfChars *chars); char_type tc_first_char_at_index(const TextCache *self, char_type idx); +bool tc_chars_at_index_without_alloc(const TextCache *self, char_type idx, ListOfChars *ans); unsigned tc_num_codepoints(const TextCache *self, char_type idx);