From a36fe45181439947a283f8483237a9a09a3f4309 Mon Sep 17 00:00:00 2001 From: MithicSpirit Date: Mon, 8 May 2023 18:46:24 -0400 Subject: [PATCH 1/4] Fix shade characters to follow unicode standard - Light shade: 25% fill - Medium shade: 50% fill - Dark shade: 75% fill (implemented as inverse of light shade) --- kitty/fonts/box_drawing.py | 41 ++++++++++---------------------------- 1 file changed, 11 insertions(+), 30 deletions(-) diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index 9e72b42d1..363ee8de9 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -617,37 +617,18 @@ def shade(buf: BufType, width: int, height: int, light: bool = False, invert: bo square_sz = max(1, width // 12) number_of_rows = height // square_sz number_of_cols = width // square_sz - nums = tuple(range(square_sz)) - - dest = bytearray(width * height) if invert else buf + nums = range(square_sz) for r in range(number_of_rows): - is_odd = r % 2 != 0 - if is_odd: - continue - fill_even = r % 4 == 0 - for yr in nums: - y = r * square_sz + yr - if y >= height: - break - off = width * y - for c in range(number_of_cols): - if light: - fill = (c % 4) == (0 if fill_even else 2) - else: - fill = (c % 2 == 0) == fill_even - if fill: - for xc in nums: - x = (c * square_sz) + xc - if x >= width: - break - dest[off + x] = 255 - if invert: - for y in range(height): - off = width * y - for x in range(width): - q = off + x - buf[q] = 255 - dest[q] + for c in range(number_of_cols): + if invert ^ ((r % 2 != c % 2) or (light and r % 2 == 1)): + continue + for yr in nums: + y = r * square_sz + yr + offset = width * y + for xc in nums: + x = c * square_sz + xc + buf[offset + x] = 255 def quad(buf: BufType, width: int, height: int, x: int = 0, y: int = 0) -> None: @@ -883,7 +864,7 @@ box_chars: Dict[str, List[Callable[[BufType, int, int], Any]]] = { '▐': [p(eight_block, which=(4, 5, 6, 7))], '░': [p(shade, light=True)], '▒': [shade], - '▓': [p(shade, invert=True)], + '▓': [p(shade, light=True, invert=True)], '▔': [p(eight_bar, horizontal=True)], '▕': [p(eight_bar, which=7)], '▖': [p(quad, y=1)], From c883a024ba2a58533fb5bea021fe6b3d2dfb11a2 Mon Sep 17 00:00:00 2001 From: MithicSpirit Date: Tue, 9 May 2023 16:08:02 -0400 Subject: [PATCH 2/4] Improve shade character appearance I was really unhappy with the previous checkerboard appearance, so I changed it to supersampled diagonal lines. The fill ratios are still the same, so it should still be compliant with the standard if I understood it correctly. Feel free to revert (or tell me to revert) this commit if you want the previous look. --- kitty/fonts/box_drawing.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index 363ee8de9..a6fa13a60 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -613,22 +613,20 @@ def inner_corner(buf: BufType, width: int, height: int, which: str = 'tl', level draw_vline(buf, width, y1, y2, width // 2 + (xd * hgap), level) +@supersampled() def shade(buf: BufType, width: int, height: int, light: bool = False, invert: bool = False) -> None: - square_sz = max(1, width // 12) - number_of_rows = height // square_sz - number_of_cols = width // square_sz - nums = range(square_sz) - - for r in range(number_of_rows): - for c in range(number_of_cols): - if invert ^ ((r % 2 != c % 2) or (light and r % 2 == 1)): - continue - for yr in nums: - y = r * square_sz + yr - offset = width * y - for xc in nums: - x = c * square_sz + xc - buf[offset + x] = 255 + x_size = width / 4 + y_size = height / 8 + pattern_segments = 4 if light else 2 + for y in range(height): + y_segment = y / y_size + offset = y * width + for x in range(width): + segment = x/x_size + y_segment + section = int(segment) % pattern_segments + enabled = section == 1 + if invert ^ enabled: + buf[offset + x] = 255 def quad(buf: BufType, width: int, height: int, x: int = 0, y: int = 0) -> None: From c247fe23364c8bf51b4a5fefc0a3c6ae5acda1f1 Mon Sep 17 00:00:00 2001 From: MithicSpirit Date: Tue, 9 May 2023 22:06:05 -0400 Subject: [PATCH 3/4] Revert "Improve shade character appearance" This reverts commit c883a024ba2a58533fb5bea021fe6b3d2dfb11a2. To maximize compatibility with the appearance in the standard. --- kitty/fonts/box_drawing.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index a6fa13a60..363ee8de9 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -613,20 +613,22 @@ def inner_corner(buf: BufType, width: int, height: int, which: str = 'tl', level draw_vline(buf, width, y1, y2, width // 2 + (xd * hgap), level) -@supersampled() def shade(buf: BufType, width: int, height: int, light: bool = False, invert: bool = False) -> None: - x_size = width / 4 - y_size = height / 8 - pattern_segments = 4 if light else 2 - for y in range(height): - y_segment = y / y_size - offset = y * width - for x in range(width): - segment = x/x_size + y_segment - section = int(segment) % pattern_segments - enabled = section == 1 - if invert ^ enabled: - buf[offset + x] = 255 + square_sz = max(1, width // 12) + number_of_rows = height // square_sz + number_of_cols = width // square_sz + nums = range(square_sz) + + for r in range(number_of_rows): + for c in range(number_of_cols): + if invert ^ ((r % 2 != c % 2) or (light and r % 2 == 1)): + continue + for yr in nums: + y = r * square_sz + yr + offset = width * y + for xc in nums: + x = c * square_sz + xc + buf[offset + x] = 255 def quad(buf: BufType, width: int, height: int, x: int = 0, y: int = 0) -> None: From 28b84a2d5b2720b88fd282fc586fa9067ec05650 Mon Sep 17 00:00:00 2001 From: MithicSpirit Date: Tue, 9 May 2023 22:16:26 -0400 Subject: [PATCH 4/4] Add support for 0x1fb90 Allocation in box_glyph_id is larger than necessary to account for the addition of 0x1fb8c ... 0x1fb94 eventually, which are quite similar but will require more work to add. Note that 0x1fb93 is not present in the standard yet, but it is easy to guess what it will likely be from context, so it should be kept in the allocation imo. --- kitty/fonts.c | 4 ++++ kitty/fonts/box_drawing.py | 1 + 2 files changed, 5 insertions(+) diff --git a/kitty/fonts.c b/kitty/fonts.c index 7771fd7df..58e3dd10c 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -543,6 +543,7 @@ START_ALLOW_CASE_RANGE case 0xe0b0 ... 0xe0bf: // powerline box drawing case 0x1fb00 ... 0x1fb8b: // symbols for legacy computing case 0x1fba0 ... 0x1fbae: + case 0x1fb90: // inverse medium shade return BOX_FONT; default: *is_emoji_presentation = has_emoji_presentation(cpu_cell, gpu_cell); @@ -585,6 +586,9 @@ START_ALLOW_CASE_RANGE return 0x151 + ch - 0x1fba0; case 0x2800 ... 0x28ff: return 0x160 + ch - 0x2800; + case 0x1fb90: + // Allocated to allow for 0x1fb8c ... 0x1fb94 eventually + return 0x25f + ch - 0x1fb8c; default: return 0xffff; } diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index 363ee8de9..d3e51a24f 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -865,6 +865,7 @@ box_chars: Dict[str, List[Callable[[BufType, int, int], Any]]] = { '░': [p(shade, light=True)], '▒': [shade], '▓': [p(shade, light=True, invert=True)], + '🮐': [p(shade, invert=True)], '▔': [p(eight_bar, horizontal=True)], '▕': [p(eight_bar, which=7)], '▖': [p(quad, y=1)],