Infra to display rendered strings as images for testing
This commit is contained in:
parent
898e87aa7b
commit
0b8e8bff16
@ -369,6 +369,7 @@ render_run(Cell *first_cell, index_type num_cells, Font UNUSED *font, FontType f
|
|||||||
|
|
||||||
void
|
void
|
||||||
render_line(Line *line) {
|
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;
|
Font *run_font = NULL;
|
||||||
FontType run_font_type = MISSING_FONT;
|
FontType run_font_type = MISSING_FONT;
|
||||||
index_type first_cell_in_run, i;
|
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);
|
FontType cell_font_type = font_for_cell(cell, &cell_font);
|
||||||
prev_width = cell->attrs & WIDTH_MASK;
|
prev_width = cell->attrs & WIDTH_MASK;
|
||||||
if (cell_font_type == run_font_type && cell_font == run_font) continue;
|
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;
|
run_font = cell_font; run_font_type = cell_font_type;
|
||||||
first_cell_in_run = i;
|
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*
|
static PyObject*
|
||||||
@ -503,6 +505,27 @@ test_render_line(PyObject UNUSED *self, PyObject *args) {
|
|||||||
Py_RETURN_NONE;
|
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[] = {
|
static PyMethodDef module_methods[] = {
|
||||||
METHODB(set_font_size, METH_VARARGS),
|
METHODB(set_font_size, METH_VARARGS),
|
||||||
METHODB(set_font, METH_VARARGS),
|
METHODB(set_font, METH_VARARGS),
|
||||||
@ -510,6 +533,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
METHODB(sprite_map_set_layout, METH_VARARGS),
|
METHODB(sprite_map_set_layout, METH_VARARGS),
|
||||||
METHODB(send_prerendered_sprites, METH_VARARGS),
|
METHODB(send_prerendered_sprites, METH_VARARGS),
|
||||||
METHODB(test_sprite_position_for, METH_VARARGS),
|
METHODB(test_sprite_position_for, METH_VARARGS),
|
||||||
|
METHODB(concat_cells, METH_VARARGS),
|
||||||
METHODB(set_send_sprite_to_gpu, METH_O),
|
METHODB(set_send_sprite_to_gpu, METH_O),
|
||||||
METHODB(test_render_line, METH_VARARGS),
|
METHODB(test_render_line, METH_VARARGS),
|
||||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||||
|
|||||||
@ -175,3 +175,37 @@ def render_box_drawing(codepoint):
|
|||||||
chr(codepoint), CharTexture(), cell_width, cell_height
|
chr(codepoint), CharTexture(), cell_width, cell_height
|
||||||
)
|
)
|
||||||
return ctypes.addressof(buf), buf
|
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()
|
||||||
|
|||||||
@ -124,7 +124,7 @@ def write_chunked(cmd, data):
|
|||||||
cmd.clear()
|
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}
|
cmd = {'a': 'T', 'f': fmt, 's': width, 'v': height}
|
||||||
set_cursor(cmd, width, height)
|
set_cursor(cmd, width, height)
|
||||||
if detect_support.has_files:
|
if detect_support.has_files:
|
||||||
|
|||||||
11
kitty/line.c
11
kitty/line.c
@ -203,6 +203,16 @@ as_unicode(Line* self) {
|
|||||||
return unicode_in_range(self, 0, xlimit_for_line(self), true, 0);
|
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
|
static inline bool
|
||||||
write_sgr(unsigned int val, Py_UCS4 *buf, index_type buflen, index_type *i) {
|
write_sgr(unsigned int val, Py_UCS4 *buf, index_type buflen, index_type *i) {
|
||||||
static char s[20] = {0};
|
static char s[20] = {0};
|
||||||
@ -584,6 +594,7 @@ static PyMethodDef methods[] = {
|
|||||||
METHOD(width, METH_O)
|
METHOD(width, METH_O)
|
||||||
METHOD(url_start_at, METH_O)
|
METHOD(url_start_at, METH_O)
|
||||||
METHOD(url_end_at, METH_O)
|
METHOD(url_end_at, METH_O)
|
||||||
|
METHOD(sprite_at, METH_O)
|
||||||
|
|
||||||
{NULL} /* Sentinel */
|
{NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user