Render known country flags designated by a pair of unicode codepoints in two cells instead of four.

This commit is contained in:
Kovid Goyal 2020-04-06 22:16:59 +05:30
parent 9bc2ab3245
commit 24197dc422
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 56 additions and 10 deletions

View File

@ -16,6 +16,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- Update to Unicode 13.0 (:iss:`2513`) - Update to Unicode 13.0 (:iss:`2513`)
- Render known country flags designated by a pair of unicode codepoints
in two cells instead of four.
0.17.2 [2020-03-29] 0.17.2 [2020-03-29]
-------------------- --------------------

View File

@ -51,7 +51,8 @@ all_symbols: Set[int] = set()
name_map: Dict[int, str] = {} name_map: Dict[int, str] = {}
word_search_map: DefaultDict[str, Set[int]] = defaultdict(set) word_search_map: DefaultDict[str, Set[int]] = defaultdict(set)
zwj = 0x200d zwj = 0x200d
marks = set(emoji_skin_tone_modifiers) | {zwj} flag_codepoints = frozenset(range(0x1F1E6, 0x1F1E6 + 26))
marks = set(emoji_skin_tone_modifiers) | {zwj} | flag_codepoints
not_assigned = set(range(0, sys.maxunicode)) not_assigned = set(range(0, sys.maxunicode))
@ -278,7 +279,7 @@ def gen_emoji() -> None:
p(comma, '{', ', '.join(map(str, arr)), '}') p(comma, '{', ', '.join(map(str, arr)), '}')
p('};') p('};')
p('if (a < 0x1F1E6 || b < 0x1F1E6 || a >= 0x1F1E6 + 26 || b >= 0x1F1E6 + 26) return false;') p('if (a < 0x1F1E6 || b < 0x1F1E6 || a >= 0x1F1E6 + 26 || b >= 0x1F1E6 + 26) return false;')
p('return flag_combinations[a][b];') p('return flag_combinations[a - 0x1F1E6][b - 0x1F1E6];')
p('};') p('};')
@ -486,7 +487,7 @@ def gen_names() -> None:
def gen_wcwidth() -> None: def gen_wcwidth() -> None:
seen: Set[int] = set() seen: Set[int] = set()
def add(p: Callable, comment: str, chars_: Set[int], ret: int) -> None: def add(p: Callable, comment: str, chars_: Union[Set[int], FrozenSet[int]], ret: int) -> None:
chars = chars_ - seen chars = chars_ - seen
seen.update(chars) seen.update(chars)
p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{') p(f'\t\t// {comment} ({len(chars)} codepoints)' + ' {{' '{')
@ -500,6 +501,7 @@ def gen_wcwidth() -> None:
p('\tswitch(code) {') p('\tswitch(code) {')
non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs'] non_printing = class_maps['Cc'] | class_maps['Cf'] | class_maps['Cs']
add(p, 'Flags', flag_codepoints, 2)
add(p, 'Marks', marks | {0}, 0) add(p, 'Marks', marks | {0}, 0)
add(p, 'Non-printing characters', non_printing, -1) add(p, 'Non-printing characters', non_printing, -1)
add(p, 'Private use', class_maps['Co'], -3) add(p, 'Private use', class_maps['Co'], -3)

2
kitty/emoji.h generated
View File

@ -811,7 +811,7 @@ static const unsigned char flag_combinations[26][26] = {
, { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 } , { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0 }
}; };
if (a < 0x1F1E6 || b < 0x1F1E6 || a >= 0x1F1E6 + 26 || b >= 0x1F1E6 + 26) return false; if (a < 0x1F1E6 || b < 0x1F1E6 || a >= 0x1F1E6 + 26 || b >= 0x1F1E6 + 26) return false;
return flag_combinations[a][b]; return flag_combinations[a - 0x1F1E6][b - 0x1F1E6];
}; };
END_ALLOW_CASE_RANGE END_ALLOW_CASE_RANGE

View File

@ -14,6 +14,7 @@
#include "fonts.h" #include "fonts.h"
#include "lineops.h" #include "lineops.h"
#include "screen.h" #include "screen.h"
#include "emoji.h"
#include <structmember.h> #include <structmember.h>
#include <limits.h> #include <limits.h>
#include <sys/types.h> #include <sys/types.h>
@ -357,6 +358,27 @@ selection_has_screen_line(Selection *s, int y) {
return top <= y && y <= bottom; return top <= y && y <= bottom;
} }
static inline bool
draw_second_flag_codepoint(Screen *self, char_type ch) {
index_type xpos = 0, ypos = 0;
if (self->cursor->x > 1) {
ypos = self->cursor->y;
xpos = self->cursor->x - 2;
} else if (self->cursor->y > 0 && self->columns > 1) {
ypos = self->cursor->y - 1;
xpos = self->columns - 2;
} else return false;
linebuf_init_line(self->linebuf, ypos);
CPUCell *cell = self->linebuf->line->cpu_cells + xpos;
if (!is_flag_pair(cell->ch, ch) || cell->cc_idx[0]) return false;
line_add_combining_char(self->linebuf->line, ch, xpos);
self->is_dirty = true;
if (selection_has_screen_line(&self->selection, ypos)) self->selection = EMPTY_SELECTION;
linebuf_mark_line_dirty(self->linebuf, ypos);
return true;
}
static inline void static inline void
draw_combining_char(Screen *self, char_type ch) { draw_combining_char(Screen *self, char_type ch) {
bool has_prev_char = false; bool has_prev_char = false;
@ -372,6 +394,17 @@ draw_combining_char(Screen *self, char_type ch) {
xpos = self->columns - 1; xpos = self->columns - 1;
has_prev_char = true; has_prev_char = true;
} }
if (self->cursor->x > 0) {
ypos = self->cursor->y;
linebuf_init_line(self->linebuf, ypos);
xpos = self->cursor->x - 1;
has_prev_char = true;
} else if (self->cursor->y > 0) {
ypos = self->cursor->y - 1;
linebuf_init_line(self->linebuf, ypos);
xpos = self->columns - 1;
has_prev_char = true;
}
if (has_prev_char) { if (has_prev_char) {
line_add_combining_char(self->linebuf->line, ch, xpos); line_add_combining_char(self->linebuf->line, ch, xpos);
self->is_dirty = true; self->is_dirty = true;
@ -412,6 +445,10 @@ screen_draw(Screen *self, uint32_t och) {
draw_combining_char(self, ch); draw_combining_char(self, ch);
return; return;
} }
bool is_flag = is_flag_codepoint(ch);
if (UNLIKELY(is_flag)) {
if (draw_second_flag_codepoint(self, ch)) return;
}
int char_width = wcwidth_std(ch); int char_width = wcwidth_std(ch);
if (UNLIKELY(char_width < 1)) { if (UNLIKELY(char_width < 1)) {
if (char_width == 0) return; if (char_width == 0) return;

7
kitty/unicode-data.c generated

File diff suppressed because one or more lines are too long

9
kitty/wcwidth-std.h generated
View File

@ -8,6 +8,11 @@ START_ALLOW_CASE_RANGE
static int static int
wcwidth_std(int32_t code) { wcwidth_std(int32_t code) {
switch(code) { switch(code) {
// Flags (26 codepoints) {{{
case 0x1f1e6 ... 0x1f1ff:
return 2;
// }}}
// Marks (2302 codepoints) {{{ // Marks (2302 codepoints) {{{
case 0x0: case 0x0:
return 0; return 0;
@ -1494,9 +1499,7 @@ wcwidth_std(int32_t code) {
return 2; return 2;
// }}} // }}}
// Emoji Presentation (26 codepoints) {{{ // Emoji Presentation (0 codepoints) {{{
case 0x1f1e6 ... 0x1f1ff:
return 2;
// }}} // }}}
// Not assigned in the unicode character database (765365 codepoints) {{{ // Not assigned in the unicode character database (765365 codepoints) {{{