diff --git a/kitty/core_text.c b/kitty/core_text.c deleted file mode 100644 index 25888e0e4..000000000 --- a/kitty/core_text.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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/core_text.m b/kitty/core_text.m new file mode 100644 index 000000000..53292b37f --- /dev/null +++ b/kitty/core_text.m @@ -0,0 +1,106 @@ +/* + * core_text.c + * Copyright (C) 2017 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#include "data-types.h" +#include +#import +#import +#import + +typedef struct { + PyObject_HEAD + + unsigned int units_per_em; + float ascent, descent, leading, underline_position, underline_thickness; + CTFontRef font; +} Face; + + +static PyObject* +new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { + Face *self; + int bold, italic; + char *cfamily; + float point_sz; + if(!PyArg_ParseTuple(args, "sppf", &cfamily, &bold, &italic, &point_sz)) return NULL; + NSString *family = [[NSString alloc] initWithCString:cfamily encoding:NSUTF8StringEncoding]; + if (family == NULL) return PyErr_NoMemory(); + self = (Face *)type->tp_alloc(type, 0); + if (self) { + CTFontSymbolicTraits symbolic_traits = (bold ? kCTFontBoldTrait : 0) | (italic ? kCTFontItalicTrait : 0); + NSDictionary *font_traits = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:symbolic_traits] forKey:(NSString *)kCTFontSymbolicTrait]; + NSDictionary *font_attributes = [NSDictionary dictionaryWithObjectsAndKeys:family, kCTFontFamilyNameAttribute, font_traits, kCTFontTraitsAttribute, nil]; + CTFontDescriptorRef descriptor = CTFontDescriptorCreateWithAttributes((CFDictionaryRef)font_attributes); + if (descriptor) { + self->font = CTFontCreateWithFontDescriptor(descriptor, point_sz, NULL); + CFRelease(descriptor); + if (!self->font) { Py_CLEAR(self); PyErr_SetString(PyExc_ValueError, "Failed to create CTFont object"); } + else { + self->units_per_em = CTFontGetUnitsPerEm(self->font); + self->ascent = CTFontGetAscent(self->font); + self->descent = CTFontGetDescent(self->font); + self->leading = CTFontGetLeading(self->font); + self->underline_position = CTFontGetUnderlinePosition(self->font); + self->underline_thickness = CTFontGetUnderlineThickness(self->font); + } + } else { + Py_CLEAR(self); + PyErr_NoMemory(); + } + } + [ family release ]; + return (PyObject*)self; +} + + +static void +dealloc(Face* self) { + if (self->font) CFRelease(self->font); + 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(ascent, T_FLOAT), + MEM(descent, T_FLOAT), + MEM(leading, T_FLOAT), + MEM(underline_position, T_FLOAT), + MEM(underline_thickness, T_FLOAT), + {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/setup.py b/setup.py index 6e1cfccdf..d98c9d26f 100755 --- a/setup.py +++ b/setup.py @@ -169,9 +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'} + exclude = {'freetype.c'} if isosx else {'core_text.m'} for x in os.listdir(d): - if x.endswith('.c') and os.path.basename(x) not in exclude: + if (x.endswith('.c') or x.endswith('.m')) 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')