summaryrefslogtreecommitdiff
path: root/src/font.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/font.c')
-rw-r--r--src/font.c611
1 files changed, 611 insertions, 0 deletions
diff --git a/src/font.c b/src/font.c
new file mode 100644
index 0000000..0bde25f
--- /dev/null
+++ b/src/font.c
@@ -0,0 +1,611 @@
+/* -*- mode: C; c-basic-offset: 2 -*-
+ *
+ * Pycairo - Python bindings for cairo
+ *
+ * Copyright © 2003 James Henstridge, Steven Chaplin
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#define PY_SSIZE_T_CLEAN
+#include <Python.h>
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "private.h"
+
+
+/* class cairo.FontFace --------------------------------------------------- */
+
+/* PycairoFontFace_FromFontFace
+ * Create a new PycairoFontFace from a cairo_font_face_t
+ * font_face - a cairo_font_face_t to 'wrap' into a Python object.
+ * it is unreferenced if the PycairoFontFace creation fails
+ * Return value: New reference or NULL on failure
+ */
+PyObject *
+PycairoFontFace_FromFontFace (cairo_font_face_t *font_face) {
+ PyTypeObject *type = NULL;
+ PyObject *o;
+
+ assert (font_face != NULL);
+
+ if (Pycairo_Check_Status (cairo_font_face_status (font_face))) {
+ cairo_font_face_destroy (font_face);
+ return NULL;
+ }
+
+ switch (cairo_font_face_get_type (font_face)) {
+ case CAIRO_FONT_TYPE_TOY:
+ type = &PycairoToyFontFace_Type;
+ break;
+ default:
+ type = &PycairoFontFace_Type;
+ break;
+ }
+ o = type->tp_alloc (type, 0);
+ if (o == NULL)
+ cairo_font_face_destroy (font_face);
+ else
+ ((PycairoFontFace *)o)->font_face = font_face;
+ return o;
+}
+
+static void
+font_face_dealloc (PycairoFontFace *o) {
+ if (o->font_face) {
+ cairo_font_face_destroy (o->font_face);
+ o->font_face = NULL;
+ }
+ o->ob_type->tp_free((PyObject *) o);
+}
+
+static PyObject *
+font_face_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ PyErr_SetString (PyExc_TypeError, "The FontFace type cannot be "
+ "instantiated directly, use Context.get_font_face()");
+ return NULL;
+}
+
+/*
+static PyMethodDef font_face_methods[] = {
+ * methods never exposed in a language binding:
+ * cairo_font_face_destroy()
+ * cairo_font_face_get_user_data()
+ * cairo_font_face_get_type()
+ * cairo_font_face_reference()
+ * cairo_font_face_set_user_data(),
+ {NULL, NULL, 0, NULL},
+};
+*/
+
+PyTypeObject PycairoFontFace_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "cairo.FontFace", /* tp_name */
+ sizeof(PycairoFontFace), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)font_face_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyBaseObject_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc)font_face_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+};
+
+
+/* class cairo.ToyFontFace ------------------------------------------------- */
+
+static PyObject *
+toy_font_face_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ PyObject *obj;
+ PyObject *pyUTF8 = NULL;
+ const char *utf8family = NULL;
+ cairo_font_slant_t slant = CAIRO_FONT_SLANT_NORMAL;
+ cairo_font_weight_t weight = CAIRO_FONT_WEIGHT_NORMAL;
+
+ if (!PyArg_ParseTuple(args, "O!|ii:ToyFontFace.__new__",
+ &PyBaseString_Type, &obj, &slant, &weight))
+ return NULL;
+
+ /* accept str and unicode family, auto convert to utf8 as required */
+ if (PyString_Check(obj)) {
+ /* A plain ASCII string is also a valid UTF-8 string */
+ utf8family = PyString_AS_STRING(obj);
+ } else if (PyUnicode_Check(obj)) {
+ pyUTF8 = PyUnicode_AsUTF8String(obj);
+ if (pyUTF8 != NULL) {
+ utf8family = PyString_AS_STRING(pyUTF8);
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "ToyFontFace.__new__: family must be str or unicode");
+ }
+ if (utf8family == NULL)
+ return NULL;
+
+ PyObject *o = PycairoFontFace_FromFontFace (
+ cairo_toy_font_face_create (utf8family, slant, weight));
+ Py_XDECREF(pyUTF8);
+ return o;
+}
+
+static PyObject *
+toy_font_get_family (PycairoToyFontFace *o) {
+ return PyString_FromString (cairo_toy_font_face_get_family (o->font_face));
+}
+
+static PyObject *
+toy_font_get_slant (PycairoToyFontFace *o) {
+ return PyInt_FromLong (cairo_toy_font_face_get_slant (o->font_face));
+}
+
+static PyObject *
+toy_font_get_weight (PycairoToyFontFace *o) {
+ return PyInt_FromLong (cairo_toy_font_face_get_weight (o->font_face));
+}
+
+static PyMethodDef toy_font_face_methods[] = {
+ {"get_family", (PyCFunction)toy_font_get_family, METH_NOARGS},
+ {"get_slant", (PyCFunction)toy_font_get_slant, METH_NOARGS},
+ {"get_weight", (PyCFunction)toy_font_get_weight, METH_NOARGS},
+ {NULL, NULL, 0, NULL},
+};
+
+
+PyTypeObject PycairoToyFontFace_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "cairo.ToyFontFace", /* tp_name */
+ sizeof(PycairoToyFontFace), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ 0, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ toy_font_face_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PycairoFontFace_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc)toy_font_face_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+};
+
+
+/* class cairo.ScaledFont ------------------------------------------------- */
+
+/* PycairoScaledFont_FromScaledFont
+ * Create a new PycairoScaledFont from a cairo_scaled_font_t
+ * scaled_font - a cairo_scaled_font_t to 'wrap' into a Python object.
+ * it is unreferenced if the PycairoScaledFont creation fails
+ * Return value: New reference or NULL on failure
+ */
+PyObject *
+PycairoScaledFont_FromScaledFont (cairo_scaled_font_t *scaled_font) {
+ PyObject *o;
+
+ assert (scaled_font != NULL);
+
+ if (Pycairo_Check_Status (cairo_scaled_font_status (scaled_font))) {
+ cairo_scaled_font_destroy (scaled_font);
+ return NULL;
+ }
+
+ o = PycairoScaledFont_Type.tp_alloc (&PycairoScaledFont_Type, 0);
+ if (o == NULL)
+ cairo_scaled_font_destroy (scaled_font);
+ else
+ ((PycairoScaledFont *)o)->scaled_font = scaled_font;
+ return o;
+}
+
+static void
+scaled_font_dealloc(PycairoScaledFont *o) {
+ if (o->scaled_font) {
+ cairo_scaled_font_destroy (o->scaled_font);
+ o->scaled_font = NULL;
+ }
+ o->ob_type->tp_free((PyObject *) o);
+}
+
+static PyObject *
+scaled_font_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ PycairoFontFace *ff;
+ PycairoFontOptions *fo;
+ PycairoMatrix *mx1, *mx2;
+
+ if (!PyArg_ParseTuple(args, "O!O!O!O!:ScaledFont.__new__",
+ &PycairoFontFace_Type, &ff,
+ &PycairoMatrix_Type, &mx1,
+ &PycairoMatrix_Type, &mx2,
+ &PycairoFontOptions_Type, &fo))
+ return NULL;
+ return PycairoScaledFont_FromScaledFont (
+ cairo_scaled_font_create (ff->font_face, &mx1->matrix,
+ &mx2->matrix, fo->font_options));
+}
+
+static PyObject *
+scaled_font_extents (PycairoScaledFont *o) {
+ cairo_font_extents_t e;
+
+ cairo_scaled_font_extents (o->scaled_font, &e);
+ RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR(o->scaled_font);
+ return Py_BuildValue ("(ddddd)", e.ascent, e.descent, e.height,
+ e.max_x_advance, e.max_y_advance);
+}
+
+static PyObject *
+scaled_font_get_font_face (PycairoScaledFont *o) {
+ return PycairoFontFace_FromFontFace (
+ cairo_font_face_reference (
+ cairo_scaled_font_get_font_face (o->scaled_font)));
+}
+
+static PyObject *
+scaled_font_get_scale_matrix (PycairoScaledFont *o) {
+ cairo_matrix_t matrix;
+ cairo_scaled_font_get_scale_matrix (o->scaled_font, &matrix);
+ return PycairoMatrix_FromMatrix (&matrix);
+}
+
+static PyObject *
+scaled_font_text_extents (PycairoScaledFont *o, PyObject *obj) {
+ cairo_text_extents_t extents;
+ PyObject *pyUTF8 = NULL;
+ const char *utf8 = NULL;
+
+ /* accept str and unicode text, auto convert to utf8 as required */
+ if (PyString_Check(obj)) {
+ /* A plain ASCII string is also a valid UTF-8 string */
+ utf8 = PyString_AS_STRING(obj);
+ } else if (PyUnicode_Check(obj)) {
+ pyUTF8 = PyUnicode_AsUTF8String(obj);
+ if (pyUTF8 != NULL) {
+ utf8 = PyString_AS_STRING(pyUTF8);
+ }
+ } else {
+ PyErr_SetString(PyExc_TypeError,
+ "ScaledFont.text_extents: text must be str or unicode");
+ }
+ if (utf8 == NULL)
+ return NULL;
+
+ cairo_scaled_font_text_extents (o->scaled_font, utf8, &extents);
+ Py_XDECREF(pyUTF8);
+ RETURN_NULL_IF_CAIRO_SCALED_FONT_ERROR(o->scaled_font);
+ return Py_BuildValue("(dddddd)", extents.x_bearing, extents.y_bearing,
+ extents.width, extents.height, extents.x_advance,
+ extents.y_advance);
+}
+
+static PyMethodDef scaled_font_methods[] = {
+ /* methods never exposed in a language binding:
+ * cairo_scaled_font_destroy()
+ * cairo_scaled_font_get_type()
+ * cairo_scaled_font_reference()
+ *
+ * TODO if requested:
+ * cairo_scaled_font_get_ctm
+ * cairo_scaled_font_get_font_matrix
+ * cairo_scaled_font_get_font_options
+ * cairo_scaled_font_glyph_extents
+ * cairo_scaled_font_text_to_glyphs
+ */
+ {"extents", (PyCFunction)scaled_font_extents, METH_NOARGS},
+ {"get_font_face", (PyCFunction)scaled_font_get_font_face, METH_NOARGS},
+ {"get_scale_matrix", (PyCFunction)scaled_font_get_scale_matrix, METH_VARARGS},
+ {"text_extents", (PyCFunction)scaled_font_text_extents, METH_O},
+ {NULL, NULL, 0, NULL},
+};
+
+
+PyTypeObject PycairoScaledFont_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "cairo.ScaledFont", /* tp_name */
+ sizeof(PycairoScaledFont), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)scaled_font_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ scaled_font_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyBaseObject_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc)scaled_font_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+};
+
+
+/* class cairo.FontOptions ------------------------------------------------ */
+
+/* PycairoFontOptions_FromFontOptions
+ * Create a new PycairoFontOptions from a cairo_font_options_t
+ * font_options - a cairo_font_options_t to 'wrap' into a Python object.
+ * it is unreferenced if the PycairoFontOptions creation fails
+ * Return value: New reference or NULL on failure
+ */
+PyObject *
+PycairoFontOptions_FromFontOptions (cairo_font_options_t *font_options) {
+ PyObject *o;
+
+ assert (font_options != NULL);
+
+ if (Pycairo_Check_Status (cairo_font_options_status (font_options))) {
+ cairo_font_options_destroy (font_options);
+ return NULL;
+ }
+
+ o = PycairoFontOptions_Type.tp_alloc (&PycairoFontOptions_Type, 0);
+ if (o == NULL)
+ cairo_font_options_destroy (font_options);
+ else
+ ((PycairoFontOptions *)o)->font_options = font_options;
+ return o;
+}
+
+static void
+font_options_dealloc(PycairoFontOptions *o) {
+ if (o->font_options) {
+ cairo_font_options_destroy (o->font_options);
+ o->font_options = NULL;
+ }
+ o->ob_type->tp_free((PyObject *) o);
+}
+
+static PyObject *
+font_options_new (PyTypeObject *type, PyObject *args, PyObject *kwds) {
+ return PycairoFontOptions_FromFontOptions (cairo_font_options_create());
+}
+
+static PyObject *
+font_options_get_antialias (PycairoFontOptions *o) {
+ return PyInt_FromLong (cairo_font_options_get_antialias (o->font_options));
+}
+
+static PyObject *
+font_options_get_hint_metrics (PycairoFontOptions *o) {
+ return PyInt_FromLong (cairo_font_options_get_hint_metrics
+ (o->font_options));
+}
+
+static PyObject *
+font_options_get_hint_style (PycairoFontOptions *o) {
+ return PyInt_FromLong (cairo_font_options_get_hint_style
+ (o->font_options));
+}
+
+static PyObject *
+font_options_get_subpixel_order (PycairoFontOptions *o) {
+ return PyInt_FromLong (cairo_font_options_get_subpixel_order
+ (o->font_options));
+}
+
+static PyObject *
+font_options_set_antialias (PycairoFontOptions *o, PyObject *args) {
+ cairo_antialias_t aa = CAIRO_ANTIALIAS_DEFAULT;
+
+ if (!PyArg_ParseTuple(args, "|i:FontOptions.set_antialias", &aa))
+ return NULL;
+
+ cairo_font_options_set_antialias (o->font_options, aa);
+ RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options);
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+font_options_set_hint_metrics (PycairoFontOptions *o, PyObject *args) {
+ cairo_hint_metrics_t hm = CAIRO_HINT_METRICS_DEFAULT;
+
+ if (!PyArg_ParseTuple(args, "|i:FontOptions.set_hint_metrics", &hm))
+ return NULL;
+
+ cairo_font_options_set_hint_metrics (o->font_options, hm);
+ RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options);
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+font_options_set_hint_style (PycairoFontOptions *o, PyObject *args) {
+ cairo_hint_style_t hs = CAIRO_HINT_STYLE_DEFAULT;
+
+ if (!PyArg_ParseTuple(args, "|i:FontOptions.set_hint_style", &hs))
+ return NULL;
+
+ cairo_font_options_set_hint_style (o->font_options, hs);
+ RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options);
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+font_options_set_subpixel_order (PycairoFontOptions *o, PyObject *args) {
+ cairo_subpixel_order_t so = CAIRO_SUBPIXEL_ORDER_DEFAULT;
+
+ if (!PyArg_ParseTuple(args, "|i:FontOptions.set_subpixel_order", &so))
+ return NULL;
+
+ cairo_font_options_set_subpixel_order (o->font_options, so);
+ RETURN_NULL_IF_CAIRO_FONT_OPTIONS_ERROR(o->font_options);
+ Py_RETURN_NONE;
+}
+
+
+static PyMethodDef font_options_methods[] = {
+ /* methods never exposed in a language binding:
+ * cairo_font_options_destroy()
+ * cairo_font_options_reference()
+ */
+ /* TODO: */
+ /* copy */
+ /* hash */
+ /* merge */
+ /* equal (richcmp?) */
+ {"get_antialias", (PyCFunction)font_options_get_antialias, METH_NOARGS},
+ {"get_hint_metrics", (PyCFunction)font_options_get_hint_metrics,
+ METH_NOARGS},
+ {"get_hint_style", (PyCFunction)font_options_get_hint_style, METH_NOARGS},
+ {"get_subpixel_order",(PyCFunction)font_options_get_subpixel_order,
+ METH_NOARGS},
+ {"set_antialias", (PyCFunction)font_options_set_antialias, METH_VARARGS},
+ {"set_hint_metrics", (PyCFunction)font_options_set_hint_metrics,
+ METH_VARARGS},
+ {"set_hint_style", (PyCFunction)font_options_set_hint_style, METH_VARARGS},
+ {"set_subpixel_order",(PyCFunction)font_options_set_subpixel_order,
+ METH_VARARGS},
+ {NULL, NULL, 0, NULL},
+};
+
+
+PyTypeObject PycairoFontOptions_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0, /* ob_size */
+ "cairo.FontOptions", /* tp_name */
+ sizeof(PycairoFontOptions), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ (destructor)font_options_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ 0, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ font_options_methods, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ &PyBaseObject_Type, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ (newfunc)font_options_new, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+};