From e45697f78a97e700989d39fadc73129545f67597 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 31 Dec 2021 09:28:47 +0530 Subject: [PATCH] Fix a regression that broke rendering of unicode regional indicators At some point, unicode regional indicators became combining chars in the unicode standard, which broke the handling of them in draw_codepoint(). The fix has the added advantage of improving performance in the common case by only checking for combining chars. The flag check happens only if the first check matches. Fixes #4407 --- kitty/screen.c | 13 +++++++------ kitty_tests/datatypes.py | 4 +++- kitty_tests/screen.py | 11 +++++++++++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/kitty/screen.c b/kitty/screen.c index 9295d4025..594b8028c 100644 --- a/kitty/screen.c +++ b/kitty/screen.c @@ -664,12 +664,13 @@ draw_codepoint(Screen *self, char_type och, bool from_input_stream) { uint32_t ch = och < 256 ? self->g_charset[och] : och; bool is_cc = is_combining_char(ch); if (UNLIKELY(is_cc)) { - draw_combining_char(self, ch); - return; - } - bool is_flag = is_flag_codepoint(ch); - if (UNLIKELY(is_flag)) { - if (draw_second_flag_codepoint(self, ch)) return; + bool is_flag = is_flag_codepoint(ch); + if (UNLIKELY(is_flag)) { + if (draw_second_flag_codepoint(self, ch)) return; + } else { + draw_combining_char(self, ch); + return; + } } int char_width = wcwidth_std(ch); if (UNLIKELY(char_width < 1)) { diff --git a/kitty_tests/datatypes.py b/kitty_tests/datatypes.py index 17e407b8c..d0128868f 100644 --- a/kitty_tests/datatypes.py +++ b/kitty_tests/datatypes.py @@ -383,8 +383,10 @@ def w(x): self.ae(wcswidth('\U0001F1E6\U0001F1E8\U0001F1E6'), 4) self.ae(wcswidth('a\u00adb'), 2) # Regional indicator symbols (unicode flags) are defined as having - # Emoji_Presentation so must have width 2 + # Emoji_Presentation so must have width 2 but combined must have + # width 2 not 4 self.ae(tuple(map(w, '\U0001f1ee\U0001f1f3')), (2, 2)) + self.ae(wcswidth('\U0001f1ee\U0001f1f3'), 2) tpl = truncate_point_for_length self.ae(tpl('abc', 4), 3) self.ae(tpl('abc', 2), 2) diff --git a/kitty_tests/screen.py b/kitty_tests/screen.py index 3f874dc1b..5ed69d2c5 100644 --- a/kitty_tests/screen.py +++ b/kitty_tests/screen.py @@ -110,6 +110,17 @@ def test_emoji_skin_tone_modifiers(self): self.ae(str(s.line(0)), q) self.ae(s.cursor.x, 2) + def test_regional_indicators(self): + s = self.create_screen() + flag = '\U0001f1ee\U0001f1f3' + s.draw(flag) + self.ae(str(s.line(0)), flag) + self.ae(s.cursor.x, 2) + s = self.create_screen() + s.draw('a'), s.draw(flag[0]), s.draw('b') + self.ae(str(s.line(0)), 'a' + flag[0] + 'b') + self.ae(s.cursor.x, 4) + def test_zwj(self): s = self.create_screen(cols=20) q = '\U0001f468\u200d\U0001f469\u200d\U0001f467\u200d\U0001f466'