Implement box drawing for Fira Code progress bar glyphs in PUA

This commit is contained in:
Kovid Goyal 2024-03-10 19:51:07 +05:30
parent 88b7595929
commit 36c79f3d50
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
2 changed files with 64 additions and 11 deletions

View file

@ -577,6 +577,7 @@ START_ALLOW_CASE_RANGE
case 0x2574 ... 0x259f:
case 0x2800 ... 0x28ff:
case 0xe0b0 ... 0xe0bf: // powerline box drawing
case 0xee00 ... 0xee05: // fira code progress bar
case 0x1fb00 ... 0x1fbae: // symbols for legacy computing
return BOX_FONT;
default:
@ -612,12 +613,12 @@ START_ALLOW_CASE_RANGE
switch(ch) {
case 0x2500 ... 0x259f:
return ch - 0x2500; // IDs from 0x00 to 0x9f
case 0xe0b0 ... 0xe0d4:
return 0xa0 + ch - 0xe0b0; // IDs from 0xa0 to 0xc4
case 0xe0b0 ... 0xee08:
return 0xa0 + ch - 0xe0b0; // IDs from 0xa0 to 0xd58
case 0x2800 ... 0x28ff:
return 0xc5 + ch - 0x2800; // IDs from 0xc5 to 0x1c4
return 0xe00 + ch - 0x2800; // IDs from 0xe00 to 0xeff
case 0x1fb00 ... 0x1fbae:
return 0x1c5 + ch - 0x1fb00; // IDs from 0x1c5 to 0x273
return 0xf00 + ch - 0x1fb00; // IDs from 0xf00 to 0xfae
default:
return 0xffff;
}

View file

@ -10,7 +10,7 @@ import math
from functools import lru_cache, wraps
from functools import partial as p
from itertools import repeat
from typing import Any, Callable, Dict, Iterable, Iterator, List, MutableSequence, Optional, Sequence, Tuple
from typing import Any, Callable, Dict, Iterable, Iterator, List, Literal, MutableSequence, Optional, Sequence, Tuple
scale = (0.001, 1., 1.5, 2.)
_dpi = 96.0
@ -787,6 +787,57 @@ def eight_block(buf: BufType, width: int, height: int, level: int = 1, which: Tu
eight_bar(buf, width, height, level, x, horizontal)
def frame(buf: BufType, width: int, height: int, edges: Tuple[Literal['l', 'r', 't', 'b'], ...] = ('l', 'r', 't', 'b'), level: int = 0) -> None:
h = thickness(level=level, horizontal=True)
v = thickness(level=level, horizontal=False)
def line(x1: int, x2: int, y1: int, y2: int) -> None:
for y in range(y1, y2):
offset = y * width
for x in range(x1, x2):
buf[x + offset] = 255
def hline(y1: int, y2: int) -> None:
line(0, width, y1, y2)
def vline(x1: int, x2: int) -> None:
line(x1, x2, 0, height)
if 't' in edges:
hline(0, h + 1)
if 'b' in edges:
hline(height - h - 1, height)
if 'l' in edges:
vline(0, v + 1)
if 'r' in edges:
vline(width - v - 1, width)
def progress_bar(buf: BufType, width: int, height: int, which: Literal['l', 'm', 'r'] = 'l', filled: bool = False, level: int = 1, gap_factor: int = 3) -> None:
if which == 'l':
frame(buf, width, height, edges=('l', 't', 'b'), level=level)
elif which == 'm':
frame(buf, width, height, edges=('t', 'b'), level=level)
else:
frame(buf, width, height, edges=('r', 't', 'b'), level=level)
if not filled:
return
h = thickness(level=level, horizontal=True)
v = thickness(level=level, horizontal=False)
y1 = gap_factor * h
y2 = height - gap_factor*h
if which == 'l':
x1, x2 = gap_factor * v, width
elif which == 'm':
x1, x2 = 0, width
else:
x1, x2 = 0, width - gap_factor*v
for y in range(y1, y2):
offset = y * width
for x in range(x1, x2):
buf[x + offset] = 255
@lru_cache(maxsize=64)
def distribute_dots(available_space: int, num_of_dots: int) -> Tuple[Tuple[int, ...], int]:
dot_size = max(1, available_space // (2 * num_of_dots))
@ -871,6 +922,12 @@ box_chars: Dict[str, List[Callable[[BufType, int, int], Any]]] = {
'': [p(cross_line, left=False)],
'': [p(corner_triangle, corner='top-right')],
'': [cross_line],
'': [p(progress_bar, which='l')],
'': [p(progress_bar, which='m')],
'': [p(progress_bar, which='r')],
'': [p(progress_bar, which='l', filled=True)],
'': [p(progress_bar, which='m', filled=True)],
'': [p(progress_bar, which='r', filled=True)],
'═': [dhline],
'║': [dvline],
@ -1101,12 +1158,7 @@ def render_box_char(ch: str, buf: BufType, width: int, height: int, dpi: float =
def render_missing_glyph(buf: BufType, width: int, height: int) -> None:
hgap = thickness(level=0, horizontal=True) + 1
vgap = thickness(level=0, horizontal=False) + 1
draw_hline(buf, width, hgap, width - hgap + 1, vgap, 0)
draw_hline(buf, width, hgap, width - hgap + 1, height - vgap, 0)
draw_vline(buf, width, vgap, height - vgap + 1, hgap, 0)
draw_vline(buf, width, vgap, height - vgap + 1, width - hgap, 0)
frame(buf, width, height)
def test_char(ch: str, sz: int = 48) -> None: