This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/python/generic/blf_py_api.c
Harley Acheson cd1631b17d BLF: Refactor of DPI
Correction of U.dpi to hold actual monitor DPI. Simplify font sizing by
omitting DPI as API argument, always using 72 internally.

See D15961 for more details.

Differential Revision: https://developer.blender.org/D15961

Reviewed by Campbell Barton
2022-09-23 17:36:49 -07:00

493 lines
16 KiB
C

/* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup pygen
*
* This file defines the 'bgl' module, used for drawing text in OpenGL.
*/
/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
#define PY_SSIZE_T_CLEAN
#include "blf_py_api.h"
#include <Python.h>
#include "../../blenfont/BLF_api.h"
#include "BLI_utildefines.h"
#include "python_utildefines.h"
PyDoc_STRVAR(py_blf_position_doc,
".. function:: position(fontid, x, y, z)\n"
"\n"
" Set the position for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg x: X axis position to draw the text.\n"
" :type x: float\n"
" :arg y: Y axis position to draw the text.\n"
" :type y: float\n"
" :arg z: Z axis position to draw the text.\n"
" :type z: float\n");
static PyObject *py_blf_position(PyObject *UNUSED(self), PyObject *args)
{
int fontid;
float x, y, z;
if (!PyArg_ParseTuple(args, "ifff:blf.position", &fontid, &x, &y, &z)) {
return NULL;
}
BLF_position(fontid, x, y, z);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_size_doc,
".. function:: size(fontid, size, dpi=72)\n"
"\n"
" Set the size for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg size: Point size of the font.\n"
" :type size: float\n"
" :arg dpi: DEPRECATED: Defaults to 72 when omitted.\n"
" :type dpi: int\n");
static PyObject *py_blf_size(PyObject *UNUSED(self), PyObject *args)
{
int fontid, dpi = -1;
float size;
if (!PyArg_ParseTuple(args, "if|i:blf.size", &fontid, &size, &dpi)) {
return NULL;
}
if (dpi != -1) {
size *= (float)dpi / 72.0f;
PyErr_WarnEx(PyExc_DeprecationWarning, "'dpi' is deprecated and assumed to be always 72.", 1);
}
BLF_size(fontid, size);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_aspect_doc,
".. function:: aspect(fontid, aspect)\n"
"\n"
" Set the aspect for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg aspect: The aspect ratio for text drawing to use.\n"
" :type aspect: float\n");
static PyObject *py_blf_aspect(PyObject *UNUSED(self), PyObject *args)
{
float aspect;
int fontid;
if (!PyArg_ParseTuple(args, "if:blf.aspect", &fontid, &aspect)) {
return NULL;
}
BLF_aspect(fontid, aspect, aspect, 1.0);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_color_doc,
".. function:: color(fontid, r, g, b, a)\n"
"\n"
" Set the color for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg r: red channel 0.0 - 1.0.\n"
" :type r: float\n"
" :arg g: green channel 0.0 - 1.0.\n"
" :type g: float\n"
" :arg b: blue channel 0.0 - 1.0.\n"
" :type b: float\n"
" :arg a: alpha channel 0.0 - 1.0.\n"
" :type a: float\n");
static PyObject *py_blf_color(PyObject *UNUSED(self), PyObject *args)
{
int fontid;
float rgba[4];
if (!PyArg_ParseTuple(
args, "iffff:blf.color", &fontid, &rgba[0], &rgba[1], &rgba[2], &rgba[3])) {
return NULL;
}
BLF_color4fv(fontid, rgba);
Py_RETURN_NONE;
}
#if BLF_BLUR_ENABLE
PyDoc_STRVAR(py_blf_blur_doc,
".. function:: blur(fontid, radius)\n"
"\n"
" Set the blur radius for drawing text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg radius: The radius for blurring text (in pixels).\n"
" :type radius: int\n");
static PyObject *py_blf_blur(PyObject *UNUSED(self), PyObject *args)
{
int blur, fontid;
if (!PyArg_ParseTuple(args, "ii:blf.blur", &fontid, &blur)) {
return NULL;
}
BLF_blur(fontid, blur);
Py_RETURN_NONE;
}
#endif
PyDoc_STRVAR(py_blf_draw_doc,
".. function:: draw(fontid, text)\n"
"\n"
" Draw text in the current context.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg text: the text to draw.\n"
" :type text: string\n");
static PyObject *py_blf_draw(PyObject *UNUSED(self), PyObject *args)
{
const char *text;
Py_ssize_t text_length;
int fontid;
if (!PyArg_ParseTuple(args, "is#:blf.draw", &fontid, &text, &text_length)) {
return NULL;
}
BLF_draw(fontid, text, (uint)text_length);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_dimensions_doc,
".. function:: dimensions(fontid, text)\n"
"\n"
" Return the width and height of the text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg text: the text to draw.\n"
" :type text: string\n"
" :return: the width and height of the text.\n"
" :rtype: tuple of 2 floats\n");
static PyObject *py_blf_dimensions(PyObject *UNUSED(self), PyObject *args)
{
const char *text;
float r_width, r_height;
PyObject *ret;
int fontid;
if (!PyArg_ParseTuple(args, "is:blf.dimensions", &fontid, &text)) {
return NULL;
}
BLF_width_and_height(fontid, text, INT_MAX, &r_width, &r_height);
ret = PyTuple_New(2);
PyTuple_SET_ITEMS(ret, PyFloat_FromDouble(r_width), PyFloat_FromDouble(r_height));
return ret;
}
PyDoc_STRVAR(py_blf_clipping_doc,
".. function:: clipping(fontid, xmin, ymin, xmax, ymax)\n"
"\n"
" Set the clipping, enable/disable using CLIPPING.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg xmin: Clip the drawing area by these bounds.\n"
" :type xmin: float\n"
" :arg ymin: Clip the drawing area by these bounds.\n"
" :type ymin: float\n"
" :arg xmax: Clip the drawing area by these bounds.\n"
" :type xmax: float\n"
" :arg ymax: Clip the drawing area by these bounds.\n"
" :type ymax: float\n");
static PyObject *py_blf_clipping(PyObject *UNUSED(self), PyObject *args)
{
float xmin, ymin, xmax, ymax;
int fontid;
if (!PyArg_ParseTuple(args, "iffff:blf.clipping", &fontid, &xmin, &ymin, &xmax, &ymax)) {
return NULL;
}
BLF_clipping(fontid, xmin, ymin, xmax, ymax);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_word_wrap_doc,
".. function:: word_wrap(fontid, wrap_width)\n"
"\n"
" Set the wrap width, enable/disable using WORD_WRAP.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg wrap_width: The width (in pixels) to wrap words at.\n"
" :type wrap_width: int\n");
static PyObject *py_blf_word_wrap(PyObject *UNUSED(self), PyObject *args)
{
int wrap_width;
int fontid;
if (!PyArg_ParseTuple(args, "ii:blf.word_wrap", &fontid, &wrap_width)) {
return NULL;
}
BLF_wordwrap(fontid, wrap_width);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_disable_doc,
".. function:: disable(fontid, option)\n"
"\n"
" Disable option.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
" :type option: int\n");
static PyObject *py_blf_disable(PyObject *UNUSED(self), PyObject *args)
{
int option, fontid;
if (!PyArg_ParseTuple(args, "ii:blf.disable", &fontid, &option)) {
return NULL;
}
BLF_disable(fontid, option);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_enable_doc,
".. function:: enable(fontid, option)\n"
"\n"
" Enable option.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
" :type option: int\n");
static PyObject *py_blf_enable(PyObject *UNUSED(self), PyObject *args)
{
int option, fontid;
if (!PyArg_ParseTuple(args, "ii:blf.enable", &fontid, &option)) {
return NULL;
}
BLF_enable(fontid, option);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_rotation_doc,
".. function:: rotation(fontid, angle)\n"
"\n"
" Set the text rotation angle, enable/disable using ROTATION.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg angle: The angle for text drawing to use.\n"
" :type angle: float\n");
static PyObject *py_blf_rotation(PyObject *UNUSED(self), PyObject *args)
{
float angle;
int fontid;
if (!PyArg_ParseTuple(args, "if:blf.rotation", &fontid, &angle)) {
return NULL;
}
BLF_rotation(fontid, angle);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_shadow_doc,
".. function:: shadow(fontid, level, r, g, b, a)\n"
"\n"
" Shadow options, enable/disable using SHADOW .\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg level: The blur level, can be 3, 5 or 0.\n"
" :type level: int\n"
" :arg r: Shadow color (red channel 0.0 - 1.0).\n"
" :type r: float\n"
" :arg g: Shadow color (green channel 0.0 - 1.0).\n"
" :type g: float\n"
" :arg b: Shadow color (blue channel 0.0 - 1.0).\n"
" :type b: float\n"
" :arg a: Shadow color (alpha channel 0.0 - 1.0).\n"
" :type a: float\n");
static PyObject *py_blf_shadow(PyObject *UNUSED(self), PyObject *args)
{
int level, fontid;
float rgba[4];
if (!PyArg_ParseTuple(
args, "iiffff:blf.shadow", &fontid, &level, &rgba[0], &rgba[1], &rgba[2], &rgba[3])) {
return NULL;
}
if (!ELEM(level, 0, 3, 5)) {
PyErr_SetString(PyExc_TypeError, "blf.shadow expected arg to be in (0, 3, 5)");
return NULL;
}
BLF_shadow(fontid, level, rgba);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_shadow_offset_doc,
".. function:: shadow_offset(fontid, x, y)\n"
"\n"
" Set the offset for shadow text.\n"
"\n"
" :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
"font use 0.\n"
" :type fontid: int\n"
" :arg x: Vertical shadow offset value in pixels.\n"
" :type x: float\n"
" :arg y: Horizontal shadow offset value in pixels.\n"
" :type y: float\n");
static PyObject *py_blf_shadow_offset(PyObject *UNUSED(self), PyObject *args)
{
int x, y, fontid;
if (!PyArg_ParseTuple(args, "iii:blf.shadow_offset", &fontid, &x, &y)) {
return NULL;
}
BLF_shadow_offset(fontid, x, y);
Py_RETURN_NONE;
}
PyDoc_STRVAR(py_blf_load_doc,
".. function:: load(filepath)\n"
"\n"
" Load a new font.\n"
"\n"
" :arg filepath: the filepath of the font.\n"
" :type filepath: string\n"
" :return: the new font's fontid or -1 if there was an error.\n"
" :rtype: integer\n");
static PyObject *py_blf_load(PyObject *UNUSED(self), PyObject *args)
{
const char *filepath;
if (!PyArg_ParseTuple(args, "s:blf.load", &filepath)) {
return NULL;
}
return PyLong_FromLong(BLF_load(filepath));
}
PyDoc_STRVAR(py_blf_unload_doc,
".. function:: unload(filepath)\n"
"\n"
" Unload an existing font.\n"
"\n"
" :arg filepath: the filepath of the font.\n"
" :type filepath: string\n");
static PyObject *py_blf_unload(PyObject *UNUSED(self), PyObject *args)
{
const char *filepath;
if (!PyArg_ParseTuple(args, "s:blf.unload", &filepath)) {
return NULL;
}
BLF_unload(filepath);
Py_RETURN_NONE;
}
/*----------------------------MODULE INIT-------------------------*/
static PyMethodDef BLF_methods[] = {
{"aspect", (PyCFunction)py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
#if BLF_BLUR_ENABLE
{"blur", (PyCFunction)py_blf_blur, METH_VARARGS, py_blf_blur_doc},
#endif
{"clipping", (PyCFunction)py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
{"word_wrap", (PyCFunction)py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
{"disable", (PyCFunction)py_blf_disable, METH_VARARGS, py_blf_disable_doc},
{"dimensions", (PyCFunction)py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
{"draw", (PyCFunction)py_blf_draw, METH_VARARGS, py_blf_draw_doc},
{"enable", (PyCFunction)py_blf_enable, METH_VARARGS, py_blf_enable_doc},
{"position", (PyCFunction)py_blf_position, METH_VARARGS, py_blf_position_doc},
{"rotation", (PyCFunction)py_blf_rotation, METH_VARARGS, py_blf_rotation_doc},
{"shadow", (PyCFunction)py_blf_shadow, METH_VARARGS, py_blf_shadow_doc},
{"shadow_offset", (PyCFunction)py_blf_shadow_offset, METH_VARARGS, py_blf_shadow_offset_doc},
{"size", (PyCFunction)py_blf_size, METH_VARARGS, py_blf_size_doc},
{"color", (PyCFunction)py_blf_color, METH_VARARGS, py_blf_color_doc},
{"load", (PyCFunction)py_blf_load, METH_VARARGS, py_blf_load_doc},
{"unload", (PyCFunction)py_blf_unload, METH_VARARGS, py_blf_unload_doc},
{NULL, NULL, 0, NULL},
};
PyDoc_STRVAR(BLF_doc, "This module provides access to Blender's text drawing functions.");
static struct PyModuleDef BLF_module_def = {
PyModuleDef_HEAD_INIT,
"blf", /* m_name */
BLF_doc, /* m_doc */
0, /* m_size */
BLF_methods, /* m_methods */
NULL, /* m_slots */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
PyObject *BPyInit_blf(void)
{
PyObject *submodule;
submodule = PyModule_Create(&BLF_module_def);
PyModule_AddIntConstant(submodule, "ROTATION", BLF_ROTATION);
PyModule_AddIntConstant(submodule, "CLIPPING", BLF_CLIPPING);
PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
PyModule_AddIntConstant(submodule, "MONOCHROME", BLF_MONOCHROME);
return submodule;
}