mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-26 10:12:17 +02:00
Add a ligature shaping test
This commit is contained in:
@@ -499,15 +499,27 @@ shape_run(Cell *first_cell, index_type num_cells, Font *font) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
test_shape(PyObject UNUSED *self, Line *line) {
|
test_shape(PyObject UNUSED *self, PyObject *args) {
|
||||||
|
Line *line;
|
||||||
|
char *path = NULL;
|
||||||
|
int index = 0;
|
||||||
|
if(!PyArg_ParseTuple(args, "O!|zi", &Line_Type, &line, &path, &index)) return NULL;
|
||||||
index_type num = 0;
|
index_type num = 0;
|
||||||
while(num < line->xnum && line->cells[num].ch) num++;
|
while(num < line->xnum && line->cells[num].ch) num++;
|
||||||
load_hb_buffer(line->cells, num);
|
load_hb_buffer(line->cells, num);
|
||||||
|
PyObject *face = NULL;
|
||||||
|
hb_font_t *hb_font;
|
||||||
Font *font = &medium_font;
|
Font *font = &medium_font;
|
||||||
hb_shape_full(font->hb_font, harfbuzz_buffer, NULL, 0, SHAPERS);
|
if (path) {
|
||||||
|
face = face_from_path(path, index);
|
||||||
|
if (face == NULL) return NULL;
|
||||||
|
hb_font = harfbuzz_font_for_face(face);
|
||||||
|
} else hb_font = font->hb_font;
|
||||||
|
hb_shape_full(hb_font, harfbuzz_buffer, NULL, 0, SHAPERS);
|
||||||
unsigned int num_glyphs;
|
unsigned int num_glyphs;
|
||||||
hb_buffer_get_glyph_infos(harfbuzz_buffer, &num_glyphs);
|
hb_buffer_get_glyph_infos(harfbuzz_buffer, &num_glyphs);
|
||||||
hb_buffer_serialize_glyphs(harfbuzz_buffer, 0, num_glyphs, (char*)canvas, CELLS_IN_CANVAS * cell_width * cell_height, NULL, font->hb_font, HB_BUFFER_SERIALIZE_FORMAT_JSON, HB_BUFFER_SERIALIZE_FLAG_DEFAULT | HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS | HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS);
|
hb_buffer_serialize_glyphs(harfbuzz_buffer, 0, num_glyphs, (char*)canvas, CELLS_IN_CANVAS * cell_width * cell_height, NULL, hb_font, HB_BUFFER_SERIALIZE_FORMAT_JSON, HB_BUFFER_SERIALIZE_FLAG_DEFAULT | HB_BUFFER_SERIALIZE_FLAG_GLYPH_EXTENTS | HB_BUFFER_SERIALIZE_FLAG_GLYPH_FLAGS);
|
||||||
|
Py_CLEAR(face);
|
||||||
return Py_BuildValue("s", canvas);
|
return Py_BuildValue("s", canvas);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -739,7 +751,7 @@ static PyMethodDef module_methods[] = {
|
|||||||
METHODB(test_sprite_position_for, METH_VARARGS),
|
METHODB(test_sprite_position_for, METH_VARARGS),
|
||||||
METHODB(concat_cells, 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_shape, METH_O),
|
METHODB(test_shape, METH_VARARGS),
|
||||||
METHODB(current_fonts, METH_NOARGS),
|
METHODB(current_fonts, METH_NOARGS),
|
||||||
METHODB(test_render_line, METH_VARARGS),
|
METHODB(test_render_line, METH_VARARGS),
|
||||||
METHODB(get_fallback_font, METH_VARARGS),
|
METHODB(get_fallback_font, METH_VARARGS),
|
||||||
|
|||||||
@@ -29,3 +29,4 @@ PyObject* ft_face_from_path_and_psname(PyObject* path, const char* psname, void
|
|||||||
PyObject* specialize_font_descriptor(PyObject *base_descriptor);
|
PyObject* specialize_font_descriptor(PyObject *base_descriptor);
|
||||||
PyObject* create_fallback_face(PyObject *base_face, Cell* cell, bool bold, bool italic);
|
PyObject* create_fallback_face(PyObject *base_face, Cell* cell, bool bold, bool italic);
|
||||||
PyObject* face_from_descriptor(PyObject*);
|
PyObject* face_from_descriptor(PyObject*);
|
||||||
|
PyObject* face_from_path(const char *path, int index);
|
||||||
|
|||||||
@@ -187,14 +187,14 @@ def render_string(text, family='monospace', size=11.0, dpi=96.0):
|
|||||||
return cell_width, cell_height, cells
|
return cell_width, cell_height, cells
|
||||||
|
|
||||||
|
|
||||||
def shape_string(text="abcd", family='monospace', size=11.0, dpi=96.0):
|
def shape_string(text="abcd", family='monospace', size=11.0, dpi=96.0, path=None):
|
||||||
import json
|
import json
|
||||||
try:
|
try:
|
||||||
sprites, cell_width, cell_height = setup_for_testing(family, size, dpi)
|
sprites, cell_width, cell_height = setup_for_testing(family, size, dpi)
|
||||||
s = Screen(None, 1, len(text)*2)
|
s = Screen(None, 1, len(text)*2)
|
||||||
line = s.line(0)
|
line = s.line(0)
|
||||||
s.draw(text)
|
s.draw(text)
|
||||||
data = test_shape(line)
|
data = test_shape(line, path)
|
||||||
return json.loads('[' + data + ']')
|
return json.loads('[' + data + ']')
|
||||||
finally:
|
finally:
|
||||||
set_send_sprite_to_gpu(None)
|
set_send_sprite_to_gpu(None)
|
||||||
|
|||||||
@@ -221,6 +221,17 @@ face_from_descriptor(PyObject *descriptor) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
PyObject*
|
||||||
|
face_from_path(const char *path, int index) {
|
||||||
|
Face *ans = (Face*)Face_Type.tp_alloc(&Face_Type, 0);
|
||||||
|
if (ans == NULL) return NULL;
|
||||||
|
int error;
|
||||||
|
error = FT_New_Face(library, path, index, &ans->face);
|
||||||
|
if (error) { set_freetype_error("Failed to load face, with error:", error); ans->face = NULL; return NULL; }
|
||||||
|
if (!init_ft_face(ans, Py_None, true, 3)) { Py_CLEAR(ans); return NULL; }
|
||||||
|
return (PyObject*)ans;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
dealloc(Face* self) {
|
dealloc(Face* self) {
|
||||||
if (self->harfbuzz_font) hb_font_destroy(self->harfbuzz_font);
|
if (self->harfbuzz_font) hb_font_destroy(self->harfbuzz_font);
|
||||||
|
|||||||
BIN
kitty_tests/FiraCode-Medium.otf
Normal file
BIN
kitty_tests/FiraCode-Medium.otf
Normal file
Binary file not shown.
@@ -70,6 +70,9 @@ class Rendering(BaseTest):
|
|||||||
self.ae(len(cells), sz)
|
self.ae(len(cells), sz)
|
||||||
|
|
||||||
def test_shaping(self):
|
def test_shaping(self):
|
||||||
self.assertEqual(len(shape_string('abcd')), 4)
|
flags = [x.get('fl', 0) for x in shape_string('abcd')]
|
||||||
|
self.ae(flags, [0, 0, 0, 0])
|
||||||
flags = [x.get('fl', 0) for x in shape_string('e\u0347\u0305')]
|
flags = [x.get('fl', 0) for x in shape_string('e\u0347\u0305')]
|
||||||
self.assertEqual(flags, [0, 1, 1])
|
self.assertEqual(flags, [0, 1, 1])
|
||||||
|
flags = [x.get('fl', 0) for x in shape_string('===', path='kitty_tests/FiraCode-Medium.otf')]
|
||||||
|
self.assertEqual(flags, [0, 1, 1])
|
||||||
|
|||||||
Reference in New Issue
Block a user