Infra to display rendered strings as images for testing

This commit is contained in:
Kovid Goyal 2017-11-02 16:35:29 +05:30
parent 898e87aa7b
commit 0b8e8bff16
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 72 additions and 3 deletions

View File

@ -369,6 +369,7 @@ render_run(Cell *first_cell, index_type num_cells, Font UNUSED *font, FontType f
void
render_line(Line *line) {
#define RENDER if ((run_font != NULL || run_font_type != FONT) && i > first_cell_in_run) render_run(line->cells + first_cell_in_run, i - first_cell_in_run, run_font, run_font_type);
Font *run_font = NULL;
FontType run_font_type = MISSING_FONT;
index_type first_cell_in_run, i;
@ -380,11 +381,12 @@ render_line(Line *line) {
FontType cell_font_type = font_for_cell(cell, &cell_font);
prev_width = cell->attrs & WIDTH_MASK;
if (cell_font_type == run_font_type && cell_font == run_font) continue;
if ((run_font != NULL || run_font_type != FONT) && i > first_cell_in_run) render_run(cell, i - first_cell_in_run, run_font, run_font_type);
RENDER;
run_font = cell_font; run_font_type = cell_font_type;
first_cell_in_run = i;
}
if ((run_font != NULL || run_font_type != FONT) && i > first_cell_in_run) render_run(line->cells + first_cell_in_run, i - first_cell_in_run, run_font, run_font_type);
RENDER;
#undef RENDER
}
static PyObject*
@ -503,6 +505,27 @@ test_render_line(PyObject UNUSED *self, PyObject *args) {
Py_RETURN_NONE;
}
static PyObject*
concat_cells(PyObject UNUSED *self, PyObject *args) {
unsigned int cell_width, cell_height;
PyObject *cells;
if (!PyArg_ParseTuple(args, "IIO!", &cell_width, &cell_height, &PyTuple_Type, &cells)) return NULL;
size_t num_cells = PyTuple_GET_SIZE(cells), r, c, i;
PyObject *ans = PyBytes_FromStringAndSize(NULL, 3 * cell_width * cell_height * num_cells);
if (ans == NULL) return PyErr_NoMemory();
uint8_t *dest = (uint8_t*)PyBytes_AS_STRING(ans), *src;
for (r = 0; r < cell_height; r++) {
for (c = 0; c < num_cells; c++) {
src = ((uint8_t*)PyBytes_AS_STRING(PyTuple_GET_ITEM(cells, c))) + cell_width * r;
for (i = 0; i < cell_width; i++, dest += 3) {
dest[0] = src[i]; dest[1] = src[i]; dest[2] = src[i];
}
}
}
return ans;
}
static PyMethodDef module_methods[] = {
METHODB(set_font_size, METH_VARARGS),
METHODB(set_font, METH_VARARGS),
@ -510,6 +533,7 @@ static PyMethodDef module_methods[] = {
METHODB(sprite_map_set_layout, METH_VARARGS),
METHODB(send_prerendered_sprites, METH_VARARGS),
METHODB(test_sprite_position_for, METH_VARARGS),
METHODB(concat_cells, METH_VARARGS),
METHODB(set_send_sprite_to_gpu, METH_O),
METHODB(test_render_line, METH_VARARGS),
{NULL, NULL, 0, NULL} /* Sentinel */

View File

@ -175,3 +175,37 @@ def render_box_drawing(codepoint):
chr(codepoint), CharTexture(), cell_width, cell_height
)
return ctypes.addressof(buf), buf
def test_render_string(text='\'Qing👁a⧽', size=200.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
if not detect_support():
raise SystemExit('Your terminal does not support the graphics protocol')
sprites = {}
def send_to_gpu(x, y, z, data):
sprites[(x, y, z)] = data
sprite_map_set_limits(100000, 100)
set_send_sprite_to_gpu(send_to_gpu)
try:
cell_width, cell_height = set_font_family(override_dpi=(dpi, dpi), override_font_size=size)
s = Screen(None, 1, len(text)*2)
line = s.line(0)
s.draw(text)
test_render_line(line)
finally:
set_send_sprite_to_gpu(None)
cells = []
for i in range(s.columns):
sp = line.sprite_at(i)
if sp != (0, 0, 0):
cells.append(sprites[sp])
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))
show(f.name, cell_width * len(cells), cell_height, 24)
print()

View File

@ -124,7 +124,7 @@ def write_chunked(cmd, data):
cmd.clear()
def show(outfile, width, height, fmt, transmit_mode):
def show(outfile, width, height, fmt, transmit_mode='t'):
cmd = {'a': 'T', 'f': fmt, 's': width, 'v': height}
set_cursor(cmd, width, height)
if detect_support.has_files:

View File

@ -203,6 +203,16 @@ as_unicode(Line* self) {
return unicode_in_range(self, 0, xlimit_for_line(self), true, 0);
}
static PyObject*
sprite_at(Line* self, PyObject *x) {
#define sprite_at_doc "[x] -> Return the sprite in the specified cell"
unsigned long xval = PyLong_AsUnsignedLong(x);
if (xval >= self->xnum) { PyErr_SetString(PyExc_IndexError, "Column number out of bounds"); return NULL; }
Cell *c = self->cells + xval;
return Py_BuildValue("HHH", c->sprite_x, c->sprite_y, c->sprite_z);
}
static inline bool
write_sgr(unsigned int val, Py_UCS4 *buf, index_type buflen, index_type *i) {
static char s[20] = {0};
@ -584,6 +594,7 @@ static PyMethodDef methods[] = {
METHOD(width, METH_O)
METHOD(url_start_at, METH_O)
METHOD(url_end_at, METH_O)
METHOD(sprite_at, METH_O)
{NULL} /* Sentinel */
};