diff --git a/kitty/fonts.c b/kitty/fonts.c index 2b17269b6..a1ceb6177 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -562,12 +562,10 @@ START_ALLOW_CASE_RANGE case ' ': case '\t': return BLANK_FONT; - case 0x2500 ... 0x2570: + case 0x2500 ... 0x2573: case 0x2574 ... 0x259f: - case 0xe0b0: //  - case 0xe0b2: //  - case 0xe0b4: //  - case 0xe0b6: //  + case 0xe0b0 ... 0xe0b4: + case 0xe0b6: case 0xe0b8: //  case 0xe0ba: //  case 0xe0bc: //  @@ -607,12 +605,8 @@ START_ALLOW_CASE_RANGE switch(ch) { case 0x2500 ... 0x259f: return ch - 0x2500; - case 0xe0b0: //  - return 0x0fa; - case 0xe0b2: //  - return 0x0fb; - case 0xe0b4: //  - return 0x0fc; + case 0xe0b0 ... 0xe0d4: + return 0xa0 + ch - 0xe0b0; case 0xe0b6: //  return 0x0fd; case 0xe0b8: //  diff --git a/kitty/fonts/box_drawing.py b/kitty/fonts/box_drawing.py index c0044287f..f10e8ed33 100644 --- a/kitty/fonts/box_drawing.py +++ b/kitty/fonts/box_drawing.py @@ -192,6 +192,97 @@ def corner_triangle(buf, width, height, corner): xlimits = [(diagonal_y(x), height - 1) for x in range(width)] fill_region(buf, width, height, xlimits) + +def antialiased_1px_line(buf, width, height, p1, p2): + # Draw an antialiased line using the Wu algorithm + x1, y1 = p1 + x2, y2 = p2 + dx, dy = x2 - x1, y2 - y1 + off_limit = height * width + steep = abs(dx) < abs(dy) + + if steep: + x1, y1, x2, y2, dx, dy = y1, x1, y2, x2, dy, dx + + def p(x, y): + return y, x + else: + def p(x, y): + return x, y + + if x2 < x1: + x1, x2, y1, y2 = x2, x1, y2, y1 + + def fpart(x): + return x - int(x) + + def rfpart(x): + return 1 - fpart(x) + + def putpixel(p, alpha): + x, y = p + off = int(x + y * width) + if 0 <= off < off_limit: + buf[off] = int(min(buf[off] + (alpha * 255), 255)) + + def draw_endpoint(pt): + x, y = pt + xend = round(x) + yend = y + grad * (xend - x) + xgap = rfpart(x + 0.5) + px, py = int(xend), int(yend) + putpixel(p(px, py), rfpart(yend) * xgap) + putpixel(p(px, py+1), fpart(yend) * xgap) + return px + + grad = dy/dx + intery = y1 + rfpart(x1) * grad + + xstart = draw_endpoint(p(*p1)) + 1 + xend = draw_endpoint(p(*p2)) + + for x in range(xstart, xend): + y = int(intery) + putpixel(p(x, y), rfpart(intery)) + putpixel(p(x, y+1), fpart(intery)) + intery += grad + + +def antialiased_line(buf, width, height, p1, p2, level=1): + th = thickness(level) + if th < 2: + return antialiased_1px_line(buf, width, height, p1, p2) + (x1, y1), (x2, y2) = p1, p2 + dh = th // 2 + items = range(-dh, dh + (th % 2)) + for delta in items: + antialiased_1px_line(buf, width, height, (x1, y1 + delta), (x2, y2 + delta)) + + +def cross_line(buf, width, height, left=True, level=1): + if left: + p1, p2 = (0, 0), (width - 1, height - 1) + else: + p1, p2 = (width - 1, 0), (0, height - 1) + antialiased_line(buf, width, height, p1, p2, level=level) + + +def half_cross_line(buf, width, height, which='tl', level=1): + my = (height - 1) // 2 + if which == 'tl': + p1 = 0, 0 + p2 = width - 1, my + elif which == 'bl': + p2 = 0, height - 1 + p1 = width - 1, my + elif which == 'tr': + p1 = width - 1, 0 + p2 = 0, my + else: + p2 = width - 1, height - 1 + p1 = 0, my + antialiased_line(buf, width, height, p1, p2, level=level) + def cubic_bezier(start, end, c1, c2): @@ -480,6 +571,8 @@ box_chars = { '': [p(triangle, left=False)], '': [D], '': [p(D, left=False)], + '': [p(half_cross_line, which='tl'), p(half_cross_line, which='bl')], + '': [p(half_cross_line, which='tr'), p(half_cross_line, which='br')], '': [p(corner_triangle, corner='bottom-left')], '': [p(corner_triangle, corner='bottom-right')], '': [p(corner_triangle, corner='top-left')], @@ -497,6 +590,9 @@ box_chars = { '╣': [p(inner_corner, which='tl'), p(inner_corner, which='bl'), p(dvline, only='right')], '╦': [p(inner_corner, which='bl'), p(inner_corner, which='br'), p(dhline, only='top')], '╩': [p(inner_corner, which='tl'), p(inner_corner, which='tr'), p(dhline, only='bottom')], + '╱': [p(cross_line, left=False)], + '╲': [cross_line], + '╳': [cross_line, p(cross_line, left=False)], '▀': [p(vblock, frac=1/2)], '▁': [p(vblock, frac=1/8, gravity='bottom')], '▂': [p(vblock, frac=1/4, gravity='bottom')],