Rendering ligatures now works

This commit is contained in:
Kovid Goyal
2017-11-04 13:15:27 +05:30
parent 1dcdf9534b
commit 6920d37042
3 changed files with 21 additions and 13 deletions

View File

@@ -387,10 +387,10 @@ set_cell_sprite(Cell *cell, SpritePosition *sp) {
}
static inline uint8_t*
extract_cell_from_canvas(unsigned int i) {
uint8_t *ans = canvas + (cell_width * cell_height * (CELLS_IN_CANVAS - 1)), *dest = ans;
uint8_t *src = canvas + (cell_width * cell_height * i);
for (unsigned int r = 0; r < cell_height; r++, dest += cell_width, src += cell_width) memcpy(dest, src, cell_width);
extract_cell_from_canvas(unsigned int i, unsigned int num_cells) {
uint8_t *ans = canvas + (cell_width * cell_height * (CELLS_IN_CANVAS - 1)), *dest = ans, *src = canvas + (i * cell_width);
unsigned int stride = cell_width * num_cells;
for (unsigned int r = 0; r < cell_height; r++, dest += cell_width, src += stride) memcpy(dest, src, cell_width);
return ans;
}
@@ -434,7 +434,7 @@ render_group(unsigned int num_cells, unsigned int num_glyphs, Cell *cells, hb_gl
for (unsigned int i = 0; i < num_cells; i++) {
sprite_position[i]->rendered = true;
set_cell_sprite(cells + i, sprite_position[i]);
uint8_t *buf = num_cells == 1 ? canvas : extract_cell_from_canvas(i);
uint8_t *buf = num_cells == 1 ? canvas : extract_cell_from_canvas(i, num_cells);
current_send_sprite_to_gpu(sprite_position[i]->x, sprite_position[i]->y, sprite_position[i]->z, buf);
}

View File

@@ -177,7 +177,7 @@ def render_box_drawing(codepoint):
return ctypes.addressof(buf), buf
def test_render_string(text='\'Qing👁a⧽', size=200.0, dpi=96.0):
def test_render_string(text='Hello, world!', family='monospace', size=144.0, dpi=96.0):
from tempfile import NamedTemporaryFile
from kitty.fast_data_types import concat_cells, set_send_sprite_to_gpu, Screen, sprite_map_set_limits, test_render_line
from kitty.icat import detect_support, show
@@ -190,8 +190,9 @@ def test_render_string(text='\'Qing👁a⧽', size=200.0, dpi=96.0):
sprite_map_set_limits(100000, 100)
set_send_sprite_to_gpu(send_to_gpu)
opts = defaults._replace(font_family=family)
try:
cell_width, cell_height = set_font_family(override_dpi=(dpi, dpi), override_font_size=size)
cell_width, cell_height = set_font_family(opts, override_dpi=(dpi, dpi), override_font_size=size)
s = Screen(None, 1, len(text)*2)
line = s.line(0)
s.draw(text)
@@ -206,6 +207,11 @@ def test_render_string(text='\'Qing👁a⧽', size=200.0, dpi=96.0):
rgb_data = concat_cells(cell_width, cell_height, tuple(cells))
with NamedTemporaryFile(delete=False) as f:
f.write(rgb_data)
print('Rendered string below: ({}x{})'.format(cell_width, cell_height))
print('Rendered string {!r} below: ({}x{})'.format(text, cell_width, cell_height))
show(f.name, cell_width * len(cells), cell_height, 24)
print()
print('\n')
def showcase():
test_render_string(family='Fira Code Medium')
test_render_string('==A=== -> -->', family='Fira Code Medium')

View File

@@ -251,12 +251,13 @@ render_bitmap(Face *self, int glyph_id, ProcessedBitmap *ans, unsigned int cell_
}
static inline void
place_bitmap_in_cell(unsigned char *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, FT_Glyph_Metrics *metrics, size_t baseline) {
place_bitmap_in_canvas(unsigned char *cell, ProcessedBitmap *bm, size_t cell_width, size_t cell_height, float x_offset, float y_offset, FT_Glyph_Metrics *metrics, size_t baseline) {
// We want the glyph to be positioned inside the cell based on the bearingX
// and bearingY values, making sure that it does not overflow the cell.
// Calculate column bounds
ssize_t xoff = (ssize_t)(x_offset + (float)metrics->horiBearingX / 64.f);
float bearing_x = (float)metrics->horiBearingX / 64.f;
ssize_t xoff = (ssize_t)(x_offset + bearing_x);
size_t src_start_column = bm->start_x, dest_start_column = 0, extra;
if (xoff < 0) src_start_column += -xoff;
else dest_start_column = xoff;
@@ -267,7 +268,8 @@ place_bitmap_in_cell(unsigned char *cell, ProcessedBitmap *bm, size_t cell_width
}
// Calculate row bounds
ssize_t yoff = (ssize_t)(y_offset + (float)metrics->horiBearingY / 64.f);
float bearing_y = (float)metrics->horiBearingY / 64.f;
ssize_t yoff = (ssize_t)(y_offset + bearing_y);
size_t src_start_row, dest_start_row;
if (yoff > 0 && (size_t)yoff > baseline) {
src_start_row = 0;
@@ -299,7 +301,7 @@ render_glyphs_in_cells(PyObject *f, bool bold, bool italic, hb_glyph_info_t *inf
if (!render_bitmap(self, info[i].codepoint, &bm, cell_width, num_cells, bold, italic, true)) return false;
x += (float)positions[i].x_offset / 64.0f;
y = (float)positions[i].y_offset / 64.0f;
place_bitmap_in_cell(canvas, &bm, cell_width * num_cells, cell_height, x, y, &self->face->glyph->metrics, baseline);
if (self->face->glyph->metrics.width > 0 && bm.width > 0) place_bitmap_in_canvas(canvas, &bm, cell_width * num_cells, cell_height, x, y, &self->face->glyph->metrics, baseline);
x += (float)positions[i].x_advance / 64.0f;
}
return true;