PyObject * Py_Outline_cnew(FT_Outline *outline) { Py_Outline *self; self = (Py_Outline *)(&Py_Outline_Type)->tp_alloc(&Py_Outline_Type, 0); if (self == NULL) { return NULL; } self->points = NULL; self->codes = NULL; self->inited = 0; if (ftpy_exc( FT_Outline_New(get_ft_library(), outline->n_points, outline->n_contours, &self->x))) { Py_DECREF(self); return NULL; } self->inited = 1; if (ftpy_exc( FT_Outline_Copy(outline, &self->x))) { Py_DECREF(self); return NULL; } self->base.owner = NULL; return (PyObject *)self; }
static PyObject* Py_Outline_check(Py_Outline* self, PyObject* args, PyObject* kwds) { if (ftpy_exc( FT_Outline_Check(&self->x))) { return NULL; } Py_RETURN_NONE; };
static PyObject* Py_Outline_get_bbox(Py_Outline* self, PyObject* args, PyObject* kwds) { FT_BBox bbox; if (ftpy_exc( FT_Outline_Get_BBox(&self->x, &bbox))) { return NULL; } return Py_BBox_cnew(&bbox, 1.0); }
static int Py_Layout_init(Py_Layout *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = {"face", "text", "load_flags", NULL}; PyObject *face_obj = NULL; Py_Face *face = NULL; PyObject *text_obj; int load_flags = FT_LOAD_DEFAULT; PyObject *text = NULL; PyObject *decoded_text = NULL; char *decoded_text_buf; Py_ssize_t decoded_text_size; int result = -1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O|i:Layout.__init__", kwlist, &Py_Face_Type, &face_obj, &text_obj, &load_flags)) { goto exit; } face = (Py_Face *)face_obj; if (face->x->charmap == NULL || face->x->charmap->encoding != FT_ENCODING_UNICODE) { PyErr_SetString( PyExc_ValueError, "The layout only supports Unicode character map"); goto exit; } text = PyUnicode_FromObject(text_obj); if (text == NULL) { goto exit; } decoded_text = PyUnicode_AsUTF32String(text); if (decoded_text == NULL) { goto exit; } if (PyBytes_AsStringAndSize(decoded_text, &decoded_text_buf, &decoded_text_size)) { goto exit; } decoded_text_buf += 4; decoded_text_size = (decoded_text_size - 4) >> 2; if (ftpy_exc(ftpy_calculate_simple_layout( face->x, load_flags, (uint32_t *)decoded_text_buf, decoded_text_size, &self->x))) { goto exit; } Py_INCREF(face_obj); self->base.owner = face_obj; result = 0; exit: Py_XDECREF(text); Py_XDECREF(decoded_text); return result; }
static PyObject* Py_Outline_to_points_and_codes(Py_Outline* self, PyObject* args, PyObject* kwds) { PyObject *result = NULL; PyObject *points = NULL; PyObject *codes = NULL; DecomposeToPointsAndCodesData data; const FT_Outline_Funcs funcs = { .move_to = Py_Outline_to_points_and_codes_moveto_func, .line_to = Py_Outline_to_points_and_codes_lineto_func, .conic_to = Py_Outline_to_points_and_codes_conicto_func, .cubic_to = Py_Outline_to_points_and_codes_cubicto_func, .shift = 0, .delta = 0 }; int error; if (!self->points || !self->codes) { memset(&data, 0, sizeof(DecomposeToPointsAndCodesData)); error = FT_Outline_Decompose(&self->x, &funcs, &data); if (PyErr_Occurred()) { PyMem_Free(data.points); PyMem_Free(data.codes); goto exit; } else if (ftpy_exc(error)) { PyMem_Free(data.points); PyMem_Free(data.codes); goto exit; } self->points = data.points; self->codes = data.codes; self->n_points = data.cursor; } points = Py_Outline_Decomposed_Points_Buffer_cnew((PyObject *)self); if (points == NULL) { goto exit; } codes = Py_Outline_Codes_Buffer_cnew((PyObject *)self); if (codes == NULL) { Py_DECREF(points); goto exit; } result = Py_BuildValue("(OO)", points, codes); if (result == NULL) { Py_DECREF(points); Py_DECREF(codes); goto exit; } exit: return result; } static PyObject* Py_Outline_to_string(Py_Outline* self, PyObject* args, PyObject* kwds) { PyObject *result = NULL; DecomposeToStringData data; const FT_Outline_Funcs funcs = { .move_to = Py_Outline_to_string_moveto_func, .line_to = Py_Outline_to_string_lineto_func, .conic_to = Py_Outline_to_string_conicto_func, .cubic_to = Py_Outline_to_string_cubicto_func, .shift = 0, .delta = 0 }; int error; const char* keywords[] = { "move_command", "line_command", "cubic_command", "conic_command", "prefix", NULL}; data.prefix = 0; data.conic_command = NULL; if (!PyArg_ParseTupleAndKeywords( args, kwds, "sss|si:to_string", (char **)keywords, &data.move_command, &data.line_command, &data.cubic_command, &data.conic_command, &data.prefix)) { return NULL; } data.buffer = PyMem_Malloc(BUFFER_CHUNK_SIZE); if (data.buffer == NULL) { return NULL; } data.buffer[0] = 0; data.buffer_size = BUFFER_CHUNK_SIZE; data.cursor = 0; data.last_x = 0; data.last_y = 0; error = FT_Outline_Decompose(&self->x, &funcs, &data); if (PyErr_Occurred()) { goto exit; } else if (ftpy_exc(error)) { goto exit; } result = PyBytes_FromStringAndSize(data.buffer, data.cursor); if (result == NULL) { goto exit; } exit: PyMem_Free(data.buffer); return result; } static PyObject* Py_Outline_translate(Py_Outline* self, PyObject* args, PyObject* kwds) { long xOffset; long yOffset; /* TODO: What is the scale of these arguments? */ const char* keywords[] = {"x_offset", "y_offset", NULL}; if (!PyArg_ParseTupleAndKeywords( args, kwds, "ll:translate", (char **)keywords, &xOffset, &yOffset)) { return NULL; } FT_Outline_Translate(&self->x, xOffset, yOffset); Py_RETURN_NONE; };
static PyObject* Py_Outline_decompose(Py_Outline* self, PyObject* args, PyObject* kwds) { /* TODO: Also implement this as an iterator */ DecomposeData data; PyObject *obj; const FT_Outline_Funcs funcs = { .move_to = Py_Outline_moveto_func, .line_to = Py_Outline_lineto_func, .conic_to = Py_Outline_conicto_func, .cubic_to = Py_Outline_cubicto_func, .shift = 0, .delta = 0 }; int error; const char* keywords[] = {"obj", "shift", "delta", NULL}; if (!PyArg_ParseTupleAndKeywords( args, kwds, "O|ii:decompose", (char **)keywords, &obj, &funcs.shift, &funcs.delta)) { return NULL; } if (!PyObject_HasAttrString(obj, "move_to")) { PyErr_SetString(PyExc_AttributeError, "obj has no move_to method"); return NULL; } if (!PyObject_HasAttrString(obj, "line_to")) { PyErr_SetString(PyExc_AttributeError, "obj has no line_to method"); return NULL; } if (!PyObject_HasAttrString(obj, "cubic_to")) { PyErr_SetString(PyExc_AttributeError, "obj has no cubic_to method"); return NULL; } data.has_conic_to = PyObject_HasAttrString(obj, "conic_to"); data.callback = obj; data.last_x = 0; data.last_y = 0; error = FT_Outline_Decompose(&self->x, &funcs, &data); if (PyErr_Occurred()) { return NULL; } else if (ftpy_exc(error)) { return NULL; } Py_RETURN_NONE; }; static PyObject* Py_Outline_embolden(Py_Outline* self, PyObject* args, PyObject* kwds) { double strength; const char* keywords[] = {"strength", NULL}; if (!PyArg_ParseTupleAndKeywords( args, kwds, "d:embolden", (char **)keywords, &strength)) { return NULL; } if (ftpy_exc( FT_Outline_Embolden(&self->x, TO_F26DOT6(strength)))) { return NULL; } Py_RETURN_NONE; };