Finish up Core Text based rendering

This commit is contained in:
Kovid Goyal 2017-01-11 14:13:37 +05:30
parent 8e7250eb7a
commit 426f960b23
3 changed files with 33 additions and 10 deletions

View File

@ -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);
}

View File

@ -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)))

View File

@ -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))