Skip to content

Commit

Permalink
Render the octant characters using box drawing
Browse files Browse the repository at this point in the history
  • Loading branch information
kovidgoyal committed Dec 26, 2024
1 parent 77e25ae commit 4dbf458
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 4 deletions.
2 changes: 1 addition & 1 deletion kitty/data-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ typedef struct ImageAnchorPosition {

#define IGNORE_PEDANTIC_WARNINGS START_IGNORE_DIAGNOSTIC("-Wpedantic")
#define END_IGNORE_PEDANTIC_WARNINGS END_IGNORE_DIAGNOSTIC
#define ALLOW_UNUSED_RESULT IGNORE_DIAGNOSTIC("-Wunused-result")
#define ALLOW_UNUSED_RESULT START_IGNORE_DIAGNOSTIC("-Wunused-result")
#define END_ALLOW_UNUSED_RESULT END_IGNORE_DIAGNOSTIC
#define START_ALLOW_CASE_RANGE IGNORE_PEDANTIC_WARNINGS
#define END_ALLOW_CASE_RANGE END_IGNORE_PEDANTIC_WARNINGS
Expand Down
86 changes: 86 additions & 0 deletions kitty/decorations.c
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,30 @@ inner_corner(Canvas *self, uint level, Corner corner) {
draw_vline(self, y1, y2, self->width / 2 + (xd * hgap), level);
}

static Range
fourth_range(uint size, uint which) {
uint thickness = max(1, size / 4);
uint block = thickness * 4;
if (block == size) return (Range){.start=thickness * which, .end=thickness * (which + 1)};
if (block > size) {
uint start = min(which * thickness, minus(size, thickness));
return (Range){.start=start, .end=start + thickness};
}
uint extra = minus(size, block);
uint thicknesses[4] = {thickness, thickness, thickness, thickness};
uint pos = 0;
if (extra) {
#define d(i) thicknesses[i]++; if (!--extra) goto done;
// ensures the thickness of first and last are least likely to be changed
d(1); d(2); d(3); d(0);
#undef d
}
done:
for (uint i = 0; i < which; i++) pos += thicknesses[i];
return (Range){.start=pos, .end=pos + thicknesses[which]};
}


static Range
eight_range(uint size, uint which) {
uint thickness = max(1, size / 8);
Expand Down Expand Up @@ -829,6 +853,67 @@ eight_bar(Canvas *self, uint which, bool horizontal) {
}
}


static void
octant_segment(Canvas *self, uint8_t which, bool left) {
Range x_range = left ? (Range){0, self->width / 2} : (Range){self->width/2, self->width};
Range y_range = fourth_range(self->height, which);
for (uint y = y_range.start; y < y_range.end; y++) {
uint offset = y * self->width;
memset(self->mask + offset + x_range.start, 255, minus(x_range.end, x_range.start));
}
}

static void
octant(Canvas *self, uint8_t which) {
enum flags { a = 1, b = 2, c = 4, d = 8, m = 16, n = 32, o = 64, p = 128 };
static const enum flags mapping[230] = {
// 00 - 0f
b, b|m, a|b|m, n, a|n, a|m|n, b|n, a|b|n, b|m|n, c, a|c, c|m, a|c|m, a|b|c, b|c|m, a|b|c|m,
// 10 - 1f
c|n, a|c|n, c|m|n, a|c|m|n, b|c|n, a|b|c|n, b|c|m|n, a|b|c|m|n, o, a|o, m|o, a|m|o, b|o, a|b|o, b|m|o, a|b|m|o,
// 20 - 2f
a|n|o, m|n|o, a|m|n|o, b|n|o, a|b|n|o, b|m|n|o, a|b|m|n|o, c|o, a|c|o, c|m|o, a|c|m|o, b|c|o, a|b|c|o, b|c|m|o, a|b|c|m|o, c|n|o,
// 30 - 3f
a|c|n|o, c|m|n|o, a|c|m|n|o, b|c|n|o, a|b|c|n|o, b|c|m|n|o, a|d, d|m, a|d|m, b|d, a|b|d, b|d|m, a|b|d|m, d|n, a|d|n, d|m|n,
// 40 - 4f
a|d|m|n, b|d|n, a|b|d|n, b|d|m|n, a|b|d|m|n, a|c|d, c|d|m, a|c|d|m, b|c|d, b|c|d|m, a|b|c|d|m, c|d|n, a|c|d|n, a|c|d|m|n, b|c|d|n, a|b|c|d|n,
// 50 - 5f
b|c|d|m|n, d|o, a|d|o, d|m|o, a|d|m|o, b|d|o, a|b|d|o, b|d|m|o, a|b|d|m|o, d|n|o, a|d|n|o, d|m|n|o, a|d|m|n|o, b|d|n|o, a|b|d|n|o, b|d|m|n|o,
// 60 - 6f
~(c|p), c|d|o, a|c|d|o, c|d|m|o, a|c|d|m|o, b|c|d|o, ~(m|n|p), b|c|d|m|o, ~(n|p), c|d|n|o, a|c|d|n|o, c|d|m|n|o, ~(b|p), b|c|d|n|o, ~(m|p), ~(a|p),
// 70 - 7f
~p, a|p, m|p, a|m|p, b|p, a|b|p, b|m|p, a|b|m|p, n|p, a|n|p, m|n|p, a|m|n|p, b|n|p, a|b|n|p, b|m|n|p, ~(c|d|o),
// 80 - 8f
c|p, a|c|p, c|m|p, a|c|m|p, b|c|p, a|b|c|p, b|c|m|p, ~(d|n|o), c|n|p, a|c|n|p, c|m|n|p, ~(b|d|o), b|c|n|p, ~(d|m|o), ~(a|d|o), ~(d|o),
// 90 - 9f
a|o|p, m|o|p, a|m|o|p, b|o|p, b|m|o|p, a|b|m|o|p, n|o|p, a|n|o|p, a|m|n|o|p, b|n|o|p, a|b|n|o|p, b|m|n|o|p, c|o|p, a|c|o|p, c|m|o|p, a|c|m|o|p,
// a0 - af
b|c|o|p, a|b|c|o|p, b|c|m|o|p, ~(n|d), c|n|o|p, a|c|n|o|p, c|m|n|o|p, ~(b|d), b|c|n|o|p, ~(d|m), ~(a|d), ~d, a|d|p, d|m|p, a|d|m|p, b|d|p,
// b0 - bf
a|b|d|p, b|d|m|p, a|b|d|m|p, d|n|p, a|d|n|p, d|m|n|p, a|d|m|n|p, b|d|n|p, a|b|d|n|p, b|d|m|n|p, ~(c|o), c|d|p, a|c|d|p, c|d|m|p, a|c|d|m|p, b|c|d|p,

// c0 -cf
a|b|c|d|p, b|c|d|m|p, ~(n|o), c|d|n|p, a|c|d|n|p, c|d|m|n|p, ~(b|o), b|c|d|n|p, ~(m|o), ~(a|o), ~o, d|o|p, a|d|o|p, d|m|o|p, a|d|m|o|p, b|d|o|p,

// d0 - df
a|b|d|o|p, b|d|m|o|p, ~(c|n), d|n|o|p, a|d|n|o|p, d|m|n|o|p, ~(b|c), b|d|n|o|p, ~(c|m), ~(a|c), ~c, a|c|d|o|p, c|d|m|o|p, ~(b|n), b|c|d|o|p, ~(a|n),
// e0 - e5
~n, c|d|n|o|p, ~(b|m), ~b, ~m, ~a,

};
which = mapping[which];
if (which & a) octant_segment(self, 0, true);
if (which & b) octant_segment(self, 1, true);
if (which & c) octant_segment(self, 2, true);
if (which & d) octant_segment(self, 3, true);
if (which & m) octant_segment(self, 0, false);
if (which & n) octant_segment(self, 1, false);
if (which & o) octant_segment(self, 2, false);
if (which & p) octant_segment(self, 3, false);

}

static void
eight_block(Canvas *self, int horizontal, ...) {
va_list args; va_start(args, horizontal);
Expand Down Expand Up @@ -1702,6 +1787,7 @@ START_ALLOW_CASE_RANGE
case 0x1fb28 ... 0x1fb28 + 19: sextant(c, ch - 0x1fb00 + 3); break;
case 0x1fb70 ... 0x1fb70 + 5: eight_bar(c, ch - 0x1fb6f, false); break;
case 0x1fb76 ... 0x1fb76 + 5: eight_bar(c, ch - 0x1fb75, true); break;
case 0x1cd00 ... 0x1cde5: octant(c, ch - 0x1cd00); true;
}
free(canvas.holes); free(canvas.y_limits);
free(ss.holes); free(ss.y_limits);
Expand Down
3 changes: 3 additions & 0 deletions kitty/fonts.c
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,7 @@ START_ALLOW_CASE_RANGE
case 0xe0b0 ... 0xe0bf: case 0xe0d6 ... 0xe0d7: // powerline box drawing
case 0xee00 ... 0xee0b: // fira code progress bar/spinner
case 0x1fb00 ... 0x1fbae: // symbols for legacy computing
case 0x1cd00 ... 0x1cde5: // octants
case 0xf5d0 ... 0xf60d: // branch drawing characters
if (allow_use_of_box_fonts) return BOX_FONT;
/* fallthrough */
Expand Down Expand Up @@ -761,6 +762,8 @@ START_ALLOW_CASE_RANGE
return 0xf00 + ch - 0x2800; // IDs from 0xf00 to 0xfff
case 0x1fb00 ... 0x1fbae:
return 0x1000 + ch - 0x1fb00; // IDs from 0x1000 to 0x10ae
case 0x1cd00 ... 0x1cde5:
return 0x1100 + ch - 0x1cd00; // IDs from 0x1100 to 0x11e5
case 0xf5d0 ... 0xf60d:
return 0x2000 + ch - 0xf5d0; // IDs from 0x2000 to 0x203d
default:
Expand Down
17 changes: 14 additions & 3 deletions kitty_tests/fonts.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,15 +435,24 @@ def test_coalesce_symbol_maps(self):
def test_chars(chars: str = '╌', sz: int = 128) -> None:
# kitty +runpy "from kitty.fonts.box_drawing import test_chars; test_chars('XXX')"
from kitty.fast_data_types import concat_cells, render_box_char, set_send_sprite_to_gpu

from .render import display_bitmap, setup_for_testing
from kitty.fonts.render import display_bitmap, setup_for_testing
if not chars:
import sys
chars = sys.argv[-1]

def as_ord(x: str) -> int:
if x.lower().startswith('u+'):
return int(x[2:], 16)
return ord(x)

if '...' in chars:
start, end = chars.partition('...')[::2]
chars = ''.join(map(chr, range(as_ord(start), as_ord(end)+1)))

with setup_for_testing('monospace', sz) as (_, width, height):
try:
for ch in chars:
nb = render_box_char(ord(ch), width, height)
nb = render_box_char(as_ord(ch), width, height)
rgb_data = concat_cells(width, height, False, (nb,))
display_bitmap(rgb_data, width, height)
print()
Expand Down Expand Up @@ -1188,3 +1197,5 @@ def render_chr(ch: str) -> bytearray:
'🮬',
'🮭',
'🮮'} # }}}
for ch in range(0x1cd00, 0x1cde5+1): # octants
box_chars.add(chr(ch))

0 comments on commit 4dbf458

Please sign in to comment.