diff --git a/kitty/core_text.m b/kitty/core_text.m index f9542e6af..b6643fb5c 100644 --- a/kitty/core_text.m +++ b/kitty/core_text.m @@ -133,13 +133,13 @@ cell_size(Face *self) { if (w > width) width = w; } } - return Py_BuildValue("I", width + 2); // + 2 for antialiasing which needs pixels on either side + return Py_BuildValue("I", width); #undef count } static PyObject* render_char(Face *self, PyObject *args) { -#define render_char_doc "" +#define render_char_doc "Render the specified character into the specified buffer. Combining unicode chars should be handled automatically (I hope)" char *s; unsigned int width, height; PyObject *pbuf; @@ -168,10 +168,11 @@ render_char(Face *self, PyObject *args) { CGContextSetTextDrawingMode(ctx, kCGTextFill); CGGlyph glyph = glyphs[0]; if (glyph) { - CGRect rect = CTFontGetBoundingRectsForGlyphs(font, kCTFontOrientationHorizontal, glyphs, 0, 1); // TODO: Scale the glyph if its bbox is larger than the image by using a non-identity transform + /* CGRect rect = CTFontGetBoundingRectsForGlyphs(font, kCTFontOrientationHorizontal, glyphs, 0, 1); */ CGContextSetTextMatrix(ctx, transform); - CGFloat pos_x = -rect.origin.x + 1, pos_y = height - rect.origin.y - rect.size.height; + CGFloat leading = self->leading > 0 ? self->leading : 1; // Ensure at least one pixel of leading so that antialiasing works at the left edge + CGFloat pos_x = leading, pos_y = height - self->ascent; CGContextSetTextPosition(ctx, pos_x, pos_y); CTFontDrawGlyphs(font, &glyph, &CGPointZero, 1, ctx); } diff --git a/kitty/fonts/core_text.py b/kitty/fonts/core_text.py index 45adca04a..a047ccaca 100644 --- a/kitty/fonts/core_text.py +++ b/kitty/fonts/core_text.py @@ -22,11 +22,10 @@ def set_font_family(family, size_in_pts): mf = main_font[(False, False)] cell_width = mf.cell_size() cell_height = ceil_int(mf.ascent + mf.descent) - cell_height += 1 * int(round(dpi / 72.0)) # some line spacing CellTexture = ctypes.c_ubyte * (cell_width * cell_height) WideCellTexture = ctypes.c_ubyte * (2 * cell_width * cell_height) baseline = int(round(mf.ascent)) - underline_position = int(round(mf.underline_position)) + underline_position = int(round(baseline - mf.underline_position)) underline_thickness = ceil_int(mf.underline_thickness) return cell_width, cell_height @@ -35,6 +34,16 @@ def current_cell(): return CellTexture, cell_width, cell_height, baseline, underline_thickness, underline_position +def split(buf, cell_width, cell_height): + first, second = CellTexture(), CellTexture() + for y in range(cell_height): + offset, woffset = y * cell_width, y * cell_width * 2 + for x in range(cell_width): + first[offset + x] = buf[woffset + x] + second[offset + x] = buf[woffset + cell_width + x] + return first, second + + def render_cell(text=' ', bold=False, italic=False): width = wcwidth(text[0]) face = main_font[(bold, italic)] @@ -43,15 +52,24 @@ def render_cell(text=' ', bold=False, italic=False): else: buf, width = CellTexture(), cell_width face.render_char(text, width, cell_height, ctypes.addressof(buf)) + if width == 2: + first, second = split(buf, cell_width, cell_height) + else: + first, second = buf, None + return first, second -def develop(): +def develop(sz=288): + import pickle from kitty.fast_data_types import glfw_init + from .render import render_string glfw_init() - set_font_family('monospace', 12.0) + set_font_family('monospace', sz) for (bold, italic), face in main_font.items(): print('bold: {} italic: {} family:{} full name: {}'.format(bold, italic, face.family_name, face.full_name)) f = main_font[(False, False)] for attr in 'units_per_em ascent descent leading underline_position underline_thickness scaled_point_sz'.split(): print(attr, getattr(f, attr)) print('cell_width: {}, cell_height: {}, baseline: {}'.format(cell_width, cell_height, baseline)) + buf, w, h = render_string(sz=200) + open('/tmp/cell.data', 'wb').write(pickle.dumps((bytearray(buf), w, h))) diff --git a/kitty/fonts/render.py b/kitty/fonts/render.py index 5966f7e2e..7bc9ceb85 100644 --- a/kitty/fonts/render.py +++ b/kitty/fonts/render.py @@ -76,7 +76,7 @@ def display_bitmap(data, w, h): img.show() -def test_rendering(text='\'Ping👁a⧽', sz=144, family='Ubuntu Mono for Kovid'): +def render_string(text='\'Qing👁a⧽', sz=144, family='monospace'): set_font_family(family, sz) cells = [] for c in text: @@ -86,4 +86,8 @@ def test_rendering(text='\'Ping👁a⧽', sz=144, family='Ubuntu Mono for Kov cells.append(s) cell_width, cell_height = current_cell()[1:3] char_data = join_cells(cell_width, cell_height, *cells) - display_bitmap(char_data, cell_width * len(cells), cell_height) + return char_data, cell_width * len(cells), cell_height + + +def test_rendering(text='\'Ping👁a⧽', sz=144, family='monospace'): + display_bitmap(*render_string(text, sz, family))