diff --git a/kitty/core_text.c b/kitty/core_text.c new file mode 100644 index 000000000..25888e0e4 --- /dev/null +++ b/kitty/core_text.c @@ -0,0 +1,76 @@ +/* + * core_text.c + * Copyright (C) 2017 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#include "data-types.h" +#include +#include + + +typedef struct { + PyObject_HEAD + + unsigned int units_per_EM; + int ascender, descender, height, max_advance_width, max_advance_height, underline_position, underline_thickness; +} Face; + + +static PyObject* +new(PyTypeObject *type, PyObject UNUSED *args, PyObject UNUSED *kwds) { + Face *self; + self = (Face *)type->tp_alloc(type, 0); + return (PyObject*)self; +} + + +static void +dealloc(Face* self) { + Py_TYPE(self)->tp_free((PyObject*)self); +} + + +// Boilerplate {{{ + +static PyMemberDef members[] = { +#define MEM(name, type) {#name, type, offsetof(Face, name), READONLY, #name} + MEM(units_per_EM, T_UINT), + MEM(ascender, T_INT), + MEM(descender, T_INT), + MEM(height, T_INT), + MEM(max_advance_width, T_INT), + MEM(max_advance_height, T_INT), + MEM(underline_position, T_INT), + MEM(underline_thickness, T_INT), + {NULL} /* Sentinel */ +}; + +static PyMethodDef methods[] = { + {NULL} /* Sentinel */ +}; + + +PyTypeObject Face_Type = { + PyVarObject_HEAD_INIT(NULL, 0) + .tp_name = "fast_data_types.CTFace", + .tp_basicsize = sizeof(Face), + .tp_dealloc = (destructor)dealloc, + .tp_flags = Py_TPFLAGS_DEFAULT, + .tp_doc = "CoreText Font face", + .tp_methods = methods, + .tp_members = members, + .tp_new = new, +}; + + +int +init_CoreText(PyObject *module) { + if (PyType_Ready(&Face_Type) < 0) return 0; + if (PyModule_AddObject(module, "CTFace", (PyObject *)&Face_Type) != 0) return 0; + return 1; +} + + +// }}} diff --git a/kitty/data-types.c b/kitty/data-types.c index bcfada2d7..4b886e702 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -63,11 +63,15 @@ PyInit_fast_data_types(void) { if (!init_SpriteMap(m)) return NULL; if (!init_ChangeTracker(m)) return NULL; if (!init_Screen(m)) return NULL; - if (!init_freetype_library(m)) return NULL; - if (!init_Face(m)) return NULL; if (!add_module_gl_constants(m)) return NULL; if (!init_glfw(m)) return NULL; if (!init_Window(m)) return NULL; +#ifdef __APPLE__ + if (!init_CoreText(m)) return NULL; +#else + if (!init_Face(m)) return NULL; + if (!init_freetype_library(m)) return NULL; +#endif PyModule_AddIntConstant(m, "BOLD", BOLD_SHIFT); PyModule_AddIntConstant(m, "ITALIC", ITALIC_SHIFT); PyModule_AddIntConstant(m, "REVERSE", REVERSE_SHIFT); diff --git a/kitty/data-types.h b/kitty/data-types.h index 29cc05a45..1bf0bfd4d 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -316,6 +316,7 @@ int init_ChangeTracker(PyObject *); int init_Screen(PyObject *); int init_Face(PyObject *); int init_Window(PyObject *); +int init_CoreText(PyObject *); PyObject* create_256_color_table(); PyObject* read_bytes_dump(PyObject UNUSED *, PyObject *); PyObject* read_bytes(PyObject UNUSED *, PyObject *); diff --git a/setup.py b/setup.py index b956b39be..6e1cfccdf 100755 --- a/setup.py +++ b/setup.py @@ -100,7 +100,11 @@ def init_env(debug=False, asan=False): if major < 2: raise SystemExit('glew >= 2.0.0 is required, found version: ' + ver) cflags.extend(pkg_config('glew', '--cflags-only-I')) - cflags.extend(pkg_config('freetype2', '--cflags-only-I')) + if isosx: + font_libs = ['-framework', 'CoreText', '-framework', 'CoreGraphics'] + else: + cflags.extend(pkg_config('freetype2', '--cflags-only-I')) + font_libs = pkg_config('freetype2', '--libs') cflags.extend(pkg_config('glfw3', '--cflags-only-I')) ldflags.append('-shared') pylib = get_python_flags(cflags) @@ -109,7 +113,7 @@ def init_env(debug=False, asan=False): else: glfw_ldflags = pkg_config('glfw3', '--libs') ldpaths = pylib + \ - pkg_config('glew', '--libs') + pkg_config('freetype2', '--libs') + glfw_ldflags + pkg_config('glew', '--libs') + font_libs + glfw_ldflags try: os.mkdir(build_dir) @@ -165,8 +169,9 @@ def option_parser(): def find_c_files(): ans = [] d = os.path.join(base, 'kitty') + exclude = {'freetype.c'} if isosx else {'core_text.c'} for x in os.listdir(d): - if x.endswith('.c'): + if x.endswith('.c') and os.path.basename(x) not in exclude: ans.append(os.path.join('kitty', x)) ans.sort(key=lambda x: os.path.getmtime(os.path.join(base, x)), reverse=True) ans.append('kitty/parser_dump.c')