diff --git a/CHANGELOG.md b/CHANGELOG.md index fef6c13f..0b0c2011 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ * PGO build scripts, in the `pgo` directory. See INSTALL.md - _Performance optimized, PGO_, for details (https://codeberg.org/dnkl/foot/issues/701). +* Braille characters (U+2800 - U+28FF) are now rendered by foot + itself (https://codeberg.org/dnkl/foot/issues/702). ### Changed diff --git a/box-drawing.c b/box-drawing.c index f246fd01..a1940392 100644 --- a/box-drawing.c +++ b/box-drawing.c @@ -1953,6 +1953,92 @@ draw_quadrant(struct buf *buf, wchar_t wc) quad_lower_right(buf); } +static void +draw_braille(struct buf *buf, wchar_t wc) +{ + int w = min(buf->width / 4, buf->height / 8); + int x_spacing = buf->width / 4; + int y_spacing = buf->height / 8; + int x_margin = x_spacing / 2; + int y_margin = y_spacing / 2; + + int x_pix_left = buf->width - 2 * x_margin - x_spacing - 2 * w; + int y_pix_left = buf->height - 2 * y_margin - 3 * y_spacing - 4 * w; + + LOG_DBG( + "braille: before adjusting: " + "cell: %dx%d, margin=%dx%d, spacing=%dx%d, width=%d, left=%dx%d", + buf->width, buf->height, x_margin, y_margin, x_spacing, y_spacing, + w, x_pix_left, y_pix_left); + + /* First, try hard to ensure the DOT width is non-zero */ + if (x_pix_left >= 2 && y_pix_left >= 4 && w == 0) { + w++; + x_pix_left -= 2; + y_pix_left -= 4; + } + + /* Second, prefer a non-zero margin */ + if (x_pix_left >= 2 && x_margin == 0) { x_margin = 1; x_pix_left -= 2; } + if (y_pix_left >= 2 && y_margin == 0) { y_margin = 1; y_pix_left -= 2; } + + if (x_pix_left >= 2 && y_pix_left >= 4) { + w++; + x_pix_left -= 2; + y_pix_left -= 4; + } + + if (x_pix_left >= 1) { x_spacing++; x_pix_left--; } + if (y_pix_left >= 3) { y_spacing++; y_pix_left -= 3; } + + if (x_pix_left >= 2) { x_margin++; x_pix_left -= 2; } + if (y_pix_left >= 2) { y_margin++; y_pix_left -= 2; } + + LOG_DBG( + "braille: after adjusting: " + "cell: %dx%d, margin=%dx%d, spacing=%dx%d, width=%d, left=%dx%d", + buf->width, buf->height, x_margin, y_margin, x_spacing, y_spacing, + w, x_pix_left, y_pix_left); + + xassert(x_pix_left <= 1 || y_pix_left <= 1); + xassert(2 * x_margin + 2 * w + x_spacing <= buf->width); + xassert(2 * y_margin + 4 * w + 3 * y_spacing <= buf->height); + + int x[2], y[4]; + x[0] = x_margin; + x[1] = x_margin + w + x_spacing; + y[0] = y_margin; + y[1] = y[0] + w + y_spacing; + y[2] = y[1] + w + y_spacing; + y[3] = y[2] + w + y_spacing; + + assert(wc >= 0x2800); + assert(wc <= 0x28ff); + uint8_t sym = wc - 0x2800; + + /* Left side */ + if (sym & 1) + rect(x[0], y[0], x[0] + w, y[0] + w); + if (sym & 2) + rect(x[0], y[1], x[0] + w, y[1] + w); + if (sym & 4) + rect(x[0], y[2], x[0] + w, y[2] + w); + + /* Right side */ + if (sym & 8) + rect(x[1], y[0], x[1] + w, y[0] + w); + if (sym & 16) + rect(x[1], y[1], x[1] + w, y[1] + w); + if (sym & 32) + rect(x[1], y[2], x[1] + w, y[2] + w); + + /* 8-dot patterns */ + if (sym & 64) + rect(x[0], y[3], x[0] + w, y[3] + w); + if (sym & 128) + rect(x[1], y[3], x[1] + w, y[3] + w); +} + static void sextant_upper_left(struct buf *buf) { @@ -2653,6 +2739,8 @@ draw_glyph(struct buf *buf, wchar_t wc) case 0x2595: draw_right_one_eighth_block(buf); break; case 0x2596 ... 0x259f: draw_quadrant(buf, wc); break; + case 0x2800 ... 0x28ff: draw_braille(buf, wc); break; + case 0x1fb00 ... 0x1fb3b: draw_sextant(buf, wc); break; case 0x1fb3c ... 0x1fb40: diff --git a/render.c b/render.c index cfb6f0bb..1cbff10d 100644 --- a/render.c +++ b/render.c @@ -515,6 +515,9 @@ render_cell(struct terminal *term, pixman_image_t *pix, /* Classic box drawings */ (base >= 0x2500 && base <= 0x259f) || + /* Braille */ + (base >= 0x2800 && base <= 0x28ff) || + /* * Unicode 13 "Symbols for Legacy Computing" * sub-ranges below. @@ -531,9 +534,12 @@ render_cell(struct terminal *term, pixman_image_t *pix, /* Box drawing characters */ size_t idx = base >= 0x1fb00 ? (base >= 0x1fb9a - ? base - 0x1fb9a + 300 - : base - 0x1fb00 + 160) - : base - 0x2500; + ? base - 0x1fb9a + 556 + : base - 0x1fb00 + 416) + : (base >= 0x2800 + ? base - 0x2800 + 160 + : base - 0x2500); + xassert(idx < ALEN(term->box_drawing)); if (likely(term->box_drawing[idx] != NULL)) @@ -541,7 +547,8 @@ render_cell(struct terminal *term, pixman_image_t *pix, else { mtx_lock(&term->render.workers.lock); - /* Parallel thread may have instantiated it while we took the lock */ + /* Other thread may have instantiated it while we + * aquired the lock */ if (term->box_drawing[idx] == NULL) term->box_drawing[idx] = box_drawing(term, base); mtx_unlock(&term->render.workers.lock); diff --git a/terminal.h b/terminal.h index 620678b1..bfb327e3 100644 --- a/terminal.h +++ b/terminal.h @@ -335,10 +335,11 @@ struct terminal { /* * 0-159: U+02500+0259F - * 160-299: U+1FB00-1FB8B - * 300-301: U+1FB9A-1FB9B + * 160-415: U+02800-028FF + * 416-555: U+1FB00-1FB8B + * 556-557: U+1FB9A-1FB9B */ - struct fcft_glyph *box_drawing[302]; + struct fcft_glyph *box_drawing[558]; bool is_sending_paste_data; ptmx_buffer_list_t ptmx_buffers;