From be505ce6e076ccae71f347f09031afc5076e530c Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 04:47:04 +0200 Subject: [PATCH 1/8] Fix test functions for setup_for_testing's new call syntax --- kitty/fonts/box_drawing.py | 84 +++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 42 deletions(-) diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index 7cd3e33cd..469d8b873 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -554,57 +554,57 @@ def test_char(ch, sz=48): # kitty +runpy "from kitty.fonts.box_drawing import test_char; import sys; test_char('XXX')" from .render import display_bitmap, setup_for_testing from kitty.fast_data_types import concat_cells, set_send_sprite_to_gpu - width, height = setup_for_testing('monospace', sz)[1:] - buf = bytearray(width * height) - try: - render_box_char(ch, buf, width, height) + with setup_for_testing('monospace', sz) as (_, width, height): + buf = bytearray(width * height) + try: + render_box_char(ch, buf, width, height) - def join_cells(*cells): - cells = tuple(bytes(x) for x in cells) - return concat_cells(width, height, False, cells) + def join_cells(*cells): + cells = tuple(bytes(x) for x in cells) + return concat_cells(width, height, False, cells) - rgb_data = join_cells(buf) - display_bitmap(rgb_data, width, height) - print() - finally: - set_send_sprite_to_gpu(None) + rgb_data = join_cells(buf) + display_bitmap(rgb_data, width, height) + print() + finally: + set_send_sprite_to_gpu(None) def test_drawing(sz=48, family='monospace'): from .render import display_bitmap, setup_for_testing from kitty.fast_data_types import concat_cells, set_send_sprite_to_gpu - width, height = setup_for_testing(family, sz)[1:] - space = bytearray(width * height) + with setup_for_testing(family, sz) as (_, width, height): + space = bytearray(width * height) - def join_cells(cells): - cells = tuple(bytes(x) for x in cells) - return concat_cells(width, height, False, cells) + def join_cells(cells): + cells = tuple(bytes(x) for x in cells) + return concat_cells(width, height, False, cells) - def render_chr(ch): - if ch in box_chars: - cell = bytearray(len(space)) - render_box_char(ch, cell, width, height) - return cell - return space + def render_chr(ch): + if ch in box_chars: + cell = bytearray(len(space)) + render_box_char(ch, cell, width, height) + return cell + return space - pos = 0x2500 - rows = [] - space_row = join_cells(repeat(space, 32)) + pos = 0x2500 + rows = [] + space_row = join_cells(repeat(space, 32)) - try: - for r in range(10): - row = [] - for i in range(16): - row.append(render_chr(chr(pos))) - row.append(space) - pos += 1 - rows.append(join_cells(row)) - rows.append(space_row) - rgb_data = b''.join(rows) - width *= 32 - height *= len(rows) - assert len(rgb_data) == width * height * 4, '{} != {}'.format(len(rgb_data), width * height * 4) - display_bitmap(rgb_data, width, height) - finally: - set_send_sprite_to_gpu(None) + try: + for r in range(10): + row = [] + for i in range(16): + row.append(render_chr(chr(pos))) + row.append(space) + pos += 1 + rows.append(join_cells(row)) + rows.append(space_row) + rgb_data = b''.join(rows) + width *= 32 + height *= len(rows) + assert len(rgb_data) == width * height * 4, '{} != {}'.format(len(rgb_data), width * height * 4) + display_bitmap(rgb_data, width, height) + finally: + set_send_sprite_to_gpu(None) From 2112932d049f3c1414e20dad289ce096a95a1da9 Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 04:48:03 +0200 Subject: [PATCH 2/8] Add corner triangle glyphs drawing --- kitty/fonts/box_drawing.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index 469d8b873..0eada38ec 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -172,6 +172,16 @@ def triangle(buf, width, height, left=True): fill_region(buf, width, height, xlimits) +def corner_triangle(buf, width, height, corner): + diagonal_y = line_equation(0, 0, width - 1, height - 1) + + if corner == 'top-right': + xlimits = [(0, diagonal_y(x)) for x in range(width)] + elif corner == 'bottom-left': + xlimits = [(diagonal_y(x), height - 1) for x in range(width)] + fill_region(buf, width, height, xlimits) + + def cubic_bezier(start, end, c1, c2): def bezier_eq(p0, p1, p2, p3): @@ -459,6 +469,8 @@ box_chars = { '': [p(triangle, left=False)], '': [D], '': [p(D, left=False)], + '': [p(corner_triangle, corner='top-right')], + '': [p(corner_triangle, corner='bottom-left')], '═': [dhline], '║': [dvline], '╞': [vline, p(half_dhline, which='right')], From 10e5fcc37535fdf6eed7f03f1c5380a2b4f0db9c Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 04:48:36 +0200 Subject: [PATCH 3/8] Fix usage of icat function `show` The `screen_size` function was not initialized yet --- kittens/icat/main.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/kittens/icat/main.py b/kittens/icat/main.py index 038f4f96b..e2c2464b5 100755 --- a/kittens/icat/main.py +++ b/kittens/icat/main.py @@ -22,7 +22,6 @@ from ..tui.images import ( ) from ..tui.operations import clear_images_on_screen, serialize_gr_command -screen_size = None OPTIONS = '''\ --align type=choices @@ -97,6 +96,16 @@ Do not print out anything to stdout during operation. ''' +screen_size = None + + +def get_screen_size(): + global screen_size + if screen_size is None: + screen_size = screen_size_function() + return screen_size() + + def options_spec(): if not hasattr(options_spec, 'ans'): options_spec.ans = OPTIONS.format( @@ -122,7 +131,7 @@ def calculate_in_cell_x_offset(width, cell_width, align): def set_cursor(cmd, width, height, align): - ss = screen_size() + ss = get_screen_size() cw = int(ss.width / ss.cols) num_of_cells_needed = int(ceil(width / cw)) if num_of_cells_needed > ss.cols: @@ -143,7 +152,7 @@ def set_cursor(cmd, width, height, align): def set_cursor_for_place(place, cmd, width, height, align): x = place.left + 1 - ss = screen_size() + ss = get_screen_size() cw = int(ss.width / ss.cols) num_of_cells_needed = int(ceil(width / cw)) cmd['X'] = calculate_in_cell_x_offset(width, cw, align) @@ -189,7 +198,7 @@ def show(outfile, width, height, fmt, transmit_mode='t', align='center', place=N def process(path, args, is_tempfile): m = identify(path) - ss = screen_size() + ss = get_screen_size() available_width = args.place.width * (ss.width / ss.cols) if args.place else ss.width available_height = args.place.height * (ss.height / ss.rows) if args.place else 10 * m.height needs_scaling = m.width > available_width or m.height > available_height @@ -334,7 +343,7 @@ def main(args=sys.argv): sys.stdin.close() sys.stdin = open(os.ctermid(), 'r') - screen_size = screen_size_function() + screen_size = get_screen_size() signal.signal(signal.SIGWINCH, lambda signum, frame: setattr(screen_size, 'changed', True)) if screen_size().width == 0: if args.detect_support: From d1cf771c1490e3bd9daf7f80df027379ec913374 Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 05:45:13 +0200 Subject: [PATCH 4/8] Add other corner triangles & enable in C side --- kitty/fonts.c | 12 ++++++++---- kitty/fonts/box_drawing.py | 23 ++++++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/kitty/fonts.c b/kitty/fonts.c index f6fa2c9a9..a672b9fd9 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -556,10 +556,14 @@ START_ALLOW_CASE_RANGE return BLANK_FONT; case 0x2500 ... 0x2570: case 0x2574 ... 0x259f: - case 0xe0b0: - case 0xe0b2: - case 0xe0b4: - case 0xe0b6: + case 0xe0b0: //  + case 0xe0b2: //  + case 0xe0b4: //  + case 0xe0b6: //  + case 0xe0b8: //  + case 0xe0ba: //  + case 0xe0bc: //  + case 0xe0be: //  return BOX_FONT; default: ans = in_symbol_maps(fg, cpu_cell->ch); diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index 0eada38ec..4b7a41f17 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -173,12 +173,19 @@ def triangle(buf, width, height, left=True): def corner_triangle(buf, width, height, corner): - diagonal_y = line_equation(0, 0, width - 1, height - 1) - - if corner == 'top-right': - xlimits = [(0, diagonal_y(x)) for x in range(width)] - elif corner == 'bottom-left': - xlimits = [(diagonal_y(x), height - 1) for x in range(width)] + print(f"corner_triangle: corner is '{corner}'") + if corner == 'top-right' or corner == 'bottom-left': + diagonal_y = line_equation(0, 0, width - 1, height - 1) + if corner == 'top-right': + xlimits = [(0, diagonal_y(x)) for x in range(width)] + elif corner == 'bottom-left': + xlimits = [(diagonal_y(x), height - 1) for x in range(width)] + else: + diagonal_y = line_equation(width - 1, 0, 0, height - 1) + if corner == 'top-left': + xlimits = [(0, diagonal_y(x)) for x in range(width)] + elif corner == 'bottom-right': + xlimits = [(diagonal_y(x), height - 1) for x in range(width)] fill_region(buf, width, height, xlimits) @@ -469,8 +476,10 @@ box_chars = { '': [p(triangle, left=False)], '': [D], '': [p(D, left=False)], - '': [p(corner_triangle, corner='top-right')], '': [p(corner_triangle, corner='bottom-left')], + '': [p(corner_triangle, corner='bottom-right')], + '': [p(corner_triangle, corner='top-left')], + '': [p(corner_triangle, corner='top-right')], '═': [dhline], '║': [dvline], '╞': [vline, p(half_dhline, which='right')], From 43a98a1df1e2a4d2ad20b8ff5d8e1bf6c4f7d8cd Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 06:08:20 +0200 Subject: [PATCH 5/8] Add missing association between char & glyph id --- kitty/fonts.c | 35 ++++++++++++++++++++++++++--------- kitty/fonts/box_drawing.py | 6 +++++- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/kitty/fonts.c b/kitty/fonts.c index a672b9fd9..2b17269b6 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -543,6 +543,14 @@ in_symbol_maps(FontGroup *fg, char_type ch) { } +// Decides which 'font' to use for a given cell. +// +// Possible results: +// - NO_FONT +// - MISSING_FONT +// - BLANK_FONT +// - BOX_FONT +// - an index in the fonts list static inline ssize_t font_for_cell(FontGroup *fg, CPUCell *cpu_cell, GPUCell *gpu_cell, bool *is_fallback_font, bool *is_emoji_presentation) { *is_fallback_font = false; @@ -592,22 +600,31 @@ set_sprite(GPUCell *cell, sprite_index x, sprite_index y, sprite_index z) { cell->sprite_x = x; cell->sprite_y = y; cell->sprite_z = z; } +// Gives a unique (arbitrary) id to a box glyph static inline glyph_index box_glyph_id(char_type ch) { START_ALLOW_CASE_RANGE switch(ch) { case 0x2500 ... 0x259f: return ch - 0x2500; - case 0xe0b0: - return 0xfa; - case 0xe0b2: - return 0xfb; - case 0xe0b4: - return 0xfc; - case 0xe0b6: - return 0xfd; + case 0xe0b0: //  + return 0x0fa; + case 0xe0b2: //  + return 0x0fb; + case 0xe0b4: //  + return 0x0fc; + case 0xe0b6: //  + return 0x0fd; + case 0xe0b8: //  + return 0x0fe; + case 0xe0ba: //  + return 0x0ff; + case 0xe0bc: //  + return 0x100; + case 0xe0be: //  + return 0x101; default: - return 0xff; + return 0xfff; } END_ALLOW_CASE_RANGE } diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index 4b7a41f17..fc78ccf51 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -2,6 +2,11 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2017, Kovid Goyal +# +# NOTE: to add a new glyph, add an entry to the `box_chars` dict, then update +# the functions `font_for_cell` and `box_glyph_id` in `kitty/fonts.c`. +# + import math from functools import partial as p from itertools import repeat @@ -173,7 +178,6 @@ def triangle(buf, width, height, left=True): def corner_triangle(buf, width, height, corner): - print(f"corner_triangle: corner is '{corner}'") if corner == 'top-right' or corner == 'bottom-left': diagonal_y = line_equation(0, 0, width - 1, height - 1) if corner == 'top-right': From f77acdce14d9e812048b2f371c8495d283d6fc8b Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 06:08:45 +0200 Subject: [PATCH 6/8] remove useless import in help msg for box drawing debug --- kitty/fonts/box_drawing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index fc78ccf51..c0044287f 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -576,7 +576,7 @@ def render_missing_glyph(buf, width, height): def test_char(ch, sz=48): - # kitty +runpy "from kitty.fonts.box_drawing import test_char; import sys; test_char('XXX')" + # kitty +runpy "from kitty.fonts.box_drawing import test_char; test_char('XXX')" from .render import display_bitmap, setup_for_testing from kitty.fast_data_types import concat_cells, set_send_sprite_to_gpu with setup_for_testing('monospace', sz) as (_, width, height): From 74deca52b9d35b527eef281db84d6f4ec9394b3b Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 11:39:51 +0200 Subject: [PATCH 7/8] Remove trailing whitespace --- kitty/fonts/box_drawing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index f10e8ed33..e87109612 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -192,7 +192,7 @@ def corner_triangle(buf, width, height, corner): xlimits = [(diagonal_y(x), height - 1) for x in range(width)] fill_region(buf, width, height, xlimits) - + def antialiased_1px_line(buf, width, height, p1, p2): # Draw an antialiased line using the Wu algorithm x1, y1 = p1 From 2b396262f070a6a65defb89fc7755ae3cfdca08c Mon Sep 17 00:00:00 2001 From: Benoit de Chezelles Date: Fri, 18 Oct 2019 11:48:55 +0200 Subject: [PATCH 8/8] Update glyph ids --- kitty/fonts.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/kitty/fonts.c b/kitty/fonts.c index a1ceb6177..5f1216dae 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -604,21 +604,21 @@ box_glyph_id(char_type ch) { START_ALLOW_CASE_RANGE switch(ch) { case 0x2500 ... 0x259f: - return ch - 0x2500; - case 0xe0b0 ... 0xe0d4: - return 0xa0 + ch - 0xe0b0; + return ch - 0x2500; // IDs from 0x00 to 0x9f + case 0xe0b0 ... 0xe0b4: + return 0xa0 + ch - 0xe0b0; // IDs from 0xa0 to 0xa4 case 0xe0b6: //  - return 0x0fd; + return 0xa5; case 0xe0b8: //  - return 0x0fe; + return 0xa6; case 0xe0ba: //  - return 0x0ff; + return 0xa7; case 0xe0bc: //  - return 0x100; + return 0xa7; case 0xe0be: //  - return 0x101; + return 0xa8; default: - return 0xfff; + return 0xff; } END_ALLOW_CASE_RANGE }