brewery
notashelf /
580ff3d36cf38bbb4377e5f3bd2248e1b04f3d2d

beer

public

A terminal worth pouring time into

Star0tarball
clone
ssh://git@git.notashelf.dev:33/notashelf/beer.git

Commit 580ff3d36cf3

tarball

NotAShelf <raf@notashelf.dev> · 2026-06-26 07:21 UTC

unverified1 files changed+43-1
render: draw braille patterns directly instead of via the font

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: I0b118f3c5e5842e37bf8427118cfc4ab6a6a6964
diff --git a/src/render.rs b/src/render.rsindex 1c01c67..4da46a7 100644--- a/src/render.rs+++ b/src/render.rs@@ -201,7 +201,12 @@ impl Renderer {             }             let (fg, _) = cell_colors(cell, theme);             let origin_x = pad_x + x as i32 * m.width as i32;-            if cell.c != ' ' {+            if is_braille(cell.c) {+                // Drawn directly so the dots are crisp and fill the cell, the+                // way tools like btop expect, rather than however the fallback+                // font happens to size its braille glyphs.+                draw_braille(&mut canvas, cell.c, origin_x, row_top, m, fg);+            } else if cell.c != ' ' {                 self.draw_glyph(&mut canvas, cell.c, cell_style(cell), origin_x, row_top, fg);             }             // Stack any combining marks over the base glyph; their own bearings@@ -432,6 +437,43 @@ fn blend_rgb(c: Rgb, toward: Rgb) -> Rgb {     Rgb(mix(c.0, toward.0), mix(c.1, toward.1), mix(c.2, toward.2)) } +/// Whether `c` is a Braille Patterns codepoint (U+2800-U+28FF).+fn is_braille(c: char) -> bool {+    ('\u{2800}'..='\u{28ff}').contains(&c)+}++/// Draw a braille pattern as a 2×4 grid of dots filling the cell. The low eight+/// bits of the codepoint select dots, numbered down each column then across:+/// `0x01 0x08 / 0x02 0x10 / 0x04 0x20 / 0x40 0x80` for (col0,col1) rows 0-3.+fn draw_braille(canvas: &mut Canvas, c: char, x0: i32, top: i32, m: CellMetrics, fg: Rgb) {+    let bits = (c as u32).wrapping_sub(0x2800) as u8;+    let (w, h) = (m.width as i32, m.height as i32);+    // Each dot owns a 1/2-width by 1/4-height sub-cell; the dot itself fills+    // most of it and is kept square so columns and rows look even.+    let sub_w = w / 2;+    let sub_h = h / 4;+    let dot = ((sub_w.min(sub_h) * 7) / 10).max(1);+    // (mask, column, row) for the eight dots.+    const DOTS: [(u8, i32, i32); 8] = [+        (0x01, 0, 0),+        (0x02, 0, 1),+        (0x04, 0, 2),+        (0x40, 0, 3),+        (0x08, 1, 0),+        (0x10, 1, 1),+        (0x20, 1, 2),+        (0x80, 1, 3),+    ];+    for (mask, col, row) in DOTS {+        if bits & mask == 0 {+            continue;+        }+        let cx = x0 + col * sub_w + sub_w / 2;+        let cy = top + row * sub_h + sub_h / 2;+        canvas.fill_rect(cx - dot / 2, cy - dot / 2, dot as u32, dot as u32, fg);+    }+}+ /// Draw underline, strikethrough, and overline for one cell. fn draw_decorations(     canvas: &mut Canvas,