diff --git a/kitty/fonts.c b/kitty/fonts.c index f439944e0..c871d2b28 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -499,15 +499,27 @@ shape_run(Cell *first_cell, index_type num_cells, Font *font) { } 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; while(num < line->xnum && line->cells[num].ch) num++; load_hb_buffer(line->cells, num); + PyObject *face = NULL; + hb_font_t *hb_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; 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); } @@ -739,7 +751,7 @@ static PyMethodDef module_methods[] = { METHODB(test_sprite_position_for, METH_VARARGS), METHODB(concat_cells, METH_VARARGS), METHODB(set_send_sprite_to_gpu, METH_O), - METHODB(test_shape, METH_O), + METHODB(test_shape, METH_VARARGS), METHODB(current_fonts, METH_NOARGS), METHODB(test_render_line, METH_VARARGS), METHODB(get_fallback_font, METH_VARARGS), diff --git a/kitty/fonts.h b/kitty/fonts.h index 9c8e889fc..3dcc6d6db 100644 --- a/kitty/fonts.h +++ b/kitty/fonts.h @@ -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* create_fallback_face(PyObject *base_face, Cell* cell, bool bold, bool italic); PyObject* face_from_descriptor(PyObject*); +PyObject* face_from_path(const char *path, int index); diff --git a/kitty/fonts/render.py b/kitty/fonts/render.py index 8122385ed..a69fa1065 100644 --- a/kitty/fonts/render.py +++ b/kitty/fonts/render.py @@ -187,14 +187,14 @@ def render_string(text, family='monospace', size=11.0, dpi=96.0): 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 try: sprites, cell_width, cell_height = setup_for_testing(family, size, dpi) s = Screen(None, 1, len(text)*2) line = s.line(0) s.draw(text) - data = test_shape(line) + data = test_shape(line, path) return json.loads('[' + data + ']') finally: set_send_sprite_to_gpu(None) diff --git a/kitty/freetype.c b/kitty/freetype.c index ffd3c32e3..b1311f0a1 100644 --- a/kitty/freetype.c +++ b/kitty/freetype.c @@ -221,6 +221,17 @@ face_from_descriptor(PyObject *descriptor) { } #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 dealloc(Face* self) { if (self->harfbuzz_font) hb_font_destroy(self->harfbuzz_font); diff --git a/kitty_tests/FiraCode-Medium.otf b/kitty_tests/FiraCode-Medium.otf new file mode 100644 index 000000000..89f0e33ae Binary files /dev/null and b/kitty_tests/FiraCode-Medium.otf differ diff --git a/kitty_tests/fonts.py b/kitty_tests/fonts.py index c4b7023a5..2c17a44ae 100644 --- a/kitty_tests/fonts.py +++ b/kitty_tests/fonts.py @@ -70,6 +70,9 @@ class Rendering(BaseTest): self.ae(len(cells), sz) 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')] 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])