Viewport: cannot select object by clicking on its instances
[blender.git] / source / blender / python / generic / blf_py_api.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup pygen
19  *
20  * This file defines the 'bgl' module, used for drawing text in OpenGL.
21  */
22
23 /* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
24 #define PY_SSIZE_T_CLEAN
25
26 #include "blf_py_api.h"
27 #include <Python.h>
28
29 #include "../../blenfont/BLF_api.h"
30
31 #include "BLI_utildefines.h"
32
33 #include "python_utildefines.h"
34
35 PyDoc_STRVAR(py_blf_position_doc,
36              ".. function:: position(fontid, x, y, z)\n"
37              "\n"
38              "   Set the position for drawing text.\n"
39              "\n"
40              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
41              "font use 0.\n"
42              "   :type fontid: int\n"
43              "   :arg x: X axis position to draw the text.\n"
44              "   :type x: float\n"
45              "   :arg y: Y axis position to draw the text.\n"
46              "   :type y: float\n"
47              "   :arg z: Z axis position to draw the text.\n"
48              "   :type z: float\n");
49
50 static PyObject *py_blf_position(PyObject *UNUSED(self), PyObject *args)
51 {
52   int fontid;
53   float x, y, z;
54
55   if (!PyArg_ParseTuple(args, "ifff:blf.position", &fontid, &x, &y, &z)) {
56     return NULL;
57   }
58
59   BLF_position(fontid, x, y, z);
60
61   Py_RETURN_NONE;
62 }
63
64 PyDoc_STRVAR(py_blf_size_doc,
65              ".. function:: size(fontid, size, dpi)\n"
66              "\n"
67              "   Set the size and dpi for drawing text.\n"
68              "\n"
69              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
70              "font use 0.\n"
71              "   :type fontid: int\n"
72              "   :arg size: Point size of the font.\n"
73              "   :type size: int\n"
74              "   :arg dpi: dots per inch value to use for drawing.\n"
75              "   :type dpi: int\n");
76 static PyObject *py_blf_size(PyObject *UNUSED(self), PyObject *args)
77 {
78   int fontid, size, dpi;
79
80   if (!PyArg_ParseTuple(args, "iii:blf.size", &fontid, &size, &dpi)) {
81     return NULL;
82   }
83
84   BLF_size(fontid, size, dpi);
85
86   Py_RETURN_NONE;
87 }
88
89 PyDoc_STRVAR(py_blf_aspect_doc,
90              ".. function:: aspect(fontid, aspect)\n"
91              "\n"
92              "   Set the aspect for drawing text.\n"
93              "\n"
94              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
95              "font use 0.\n"
96              "   :type fontid: int\n"
97              "   :arg aspect: The aspect ratio for text drawing to use.\n"
98              "   :type aspect: float\n");
99 static PyObject *py_blf_aspect(PyObject *UNUSED(self), PyObject *args)
100 {
101   float aspect;
102   int fontid;
103
104   if (!PyArg_ParseTuple(args, "if:blf.aspect", &fontid, &aspect)) {
105     return NULL;
106   }
107
108   BLF_aspect(fontid, aspect, aspect, 1.0);
109
110   Py_RETURN_NONE;
111 }
112
113 PyDoc_STRVAR(py_blf_color_doc,
114              ".. function:: color(fontid, r, g, b, a)\n"
115              "\n"
116              "   Set the color for drawing text.\n"
117              "\n"
118              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
119              "font use 0.\n"
120              "   :type fontid: int\n"
121              "   :arg r: red channel 0.0 - 1.0.\n"
122              "   :type r: float\n"
123              "   :arg g: green channel 0.0 - 1.0.\n"
124              "   :type g: float\n"
125              "   :arg b: blue channel 0.0 - 1.0.\n"
126              "   :type b: float\n"
127              "   :arg a: alpha channel 0.0 - 1.0.\n"
128              "   :type a: float\n");
129 static PyObject *py_blf_color(PyObject *UNUSED(self), PyObject *args)
130 {
131   int fontid;
132   float rgba[4];
133
134   if (!PyArg_ParseTuple(
135           args, "iffff:blf.color", &fontid, &rgba[0], &rgba[1], &rgba[2], &rgba[3])) {
136     return NULL;
137   }
138
139   BLF_color4fv(fontid, rgba);
140
141   Py_RETURN_NONE;
142 }
143
144 #if BLF_BLUR_ENABLE
145 PyDoc_STRVAR(py_blf_blur_doc,
146              ".. function:: blur(fontid, radius)\n"
147              "\n"
148              "   Set the blur radius for drawing text.\n"
149              "\n"
150              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
151              "font use 0.\n"
152              "   :type fontid: int\n"
153              "   :arg radius: The radius for blurring text (in pixels).\n"
154              "   :type radius: int\n");
155 static PyObject *py_blf_blur(PyObject *UNUSED(self), PyObject *args)
156 {
157   int blur, fontid;
158
159   if (!PyArg_ParseTuple(args, "ii:blf.blur", &fontid, &blur)) {
160     return NULL;
161   }
162
163   BLF_blur(fontid, blur);
164
165   Py_RETURN_NONE;
166 }
167 #endif
168
169 PyDoc_STRVAR(py_blf_draw_doc,
170              ".. function:: draw(fontid, text)\n"
171              "\n"
172              "   Draw text in the current context.\n"
173              "\n"
174              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
175              "font use 0.\n"
176              "   :type fontid: int\n"
177              "   :arg text: the text to draw.\n"
178              "   :type text: string\n");
179 static PyObject *py_blf_draw(PyObject *UNUSED(self), PyObject *args)
180 {
181   const char *text;
182   Py_ssize_t text_length;
183   int fontid;
184
185   if (!PyArg_ParseTuple(args, "is#:blf.draw", &fontid, &text, &text_length)) {
186     return NULL;
187   }
188
189   BLF_draw(fontid, text, (uint)text_length);
190
191   Py_RETURN_NONE;
192 }
193
194 PyDoc_STRVAR(py_blf_dimensions_doc,
195              ".. function:: dimensions(fontid, text)\n"
196              "\n"
197              "   Return the width and height of the text.\n"
198              "\n"
199              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
200              "font use 0.\n"
201              "   :type fontid: int\n"
202              "   :arg text: the text to draw.\n"
203              "   :type text: string\n"
204              "   :return: the width and height of the text.\n"
205              "   :rtype: tuple of 2 floats\n");
206 static PyObject *py_blf_dimensions(PyObject *UNUSED(self), PyObject *args)
207 {
208   const char *text;
209   float r_width, r_height;
210   PyObject *ret;
211   int fontid;
212
213   if (!PyArg_ParseTuple(args, "is:blf.dimensions", &fontid, &text)) {
214     return NULL;
215   }
216
217   BLF_width_and_height(fontid, text, INT_MAX, &r_width, &r_height);
218
219   ret = PyTuple_New(2);
220   PyTuple_SET_ITEMS(ret, PyFloat_FromDouble(r_width), PyFloat_FromDouble(r_height));
221   return ret;
222 }
223
224 PyDoc_STRVAR(py_blf_clipping_doc,
225              ".. function:: clipping(fontid, xmin, ymin, xmax, ymax)\n"
226              "\n"
227              "   Set the clipping, enable/disable using CLIPPING.\n"
228              "\n"
229              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
230              "font use 0.\n"
231              "   :type fontid: int\n"
232              "   :arg xmin: Clip the drawing area by these bounds.\n"
233              "   :type xmin: float\n"
234              "   :arg ymin: Clip the drawing area by these bounds.\n"
235              "   :type ymin: float\n"
236              "   :arg xmax: Clip the drawing area by these bounds.\n"
237              "   :type xmax: float\n"
238              "   :arg ymax: Clip the drawing area by these bounds.\n"
239              "   :type ymax: float\n");
240 static PyObject *py_blf_clipping(PyObject *UNUSED(self), PyObject *args)
241 {
242   float xmin, ymin, xmax, ymax;
243   int fontid;
244
245   if (!PyArg_ParseTuple(args, "iffff:blf.clipping", &fontid, &xmin, &ymin, &xmax, &ymax)) {
246     return NULL;
247   }
248
249   BLF_clipping(fontid, xmin, ymin, xmax, ymax);
250
251   Py_RETURN_NONE;
252 }
253
254 PyDoc_STRVAR(py_blf_word_wrap_doc,
255              ".. function:: word_wrap(fontid, wrap_width)\n"
256              "\n"
257              "   Set the wrap width, enable/disable using WORD_WRAP.\n"
258              "\n"
259              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
260              "font use 0.\n"
261              "   :type fontid: int\n"
262              "   :arg wrap_width: The width (in pixels) to wrap words at.\n"
263              "   :type wrap_width: int\n");
264 static PyObject *py_blf_word_wrap(PyObject *UNUSED(self), PyObject *args)
265 {
266   int wrap_width;
267   int fontid;
268
269   if (!PyArg_ParseTuple(args, "ii:blf.word_wrap", &fontid, &wrap_width)) {
270     return NULL;
271   }
272
273   BLF_wordwrap(fontid, wrap_width);
274
275   Py_RETURN_NONE;
276 }
277
278 PyDoc_STRVAR(py_blf_disable_doc,
279              ".. function:: disable(fontid, option)\n"
280              "\n"
281              "   Disable option.\n"
282              "\n"
283              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
284              "font use 0.\n"
285              "   :type fontid: int\n"
286              "   :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
287              "   :type option: int\n");
288 static PyObject *py_blf_disable(PyObject *UNUSED(self), PyObject *args)
289 {
290   int option, fontid;
291
292   if (!PyArg_ParseTuple(args, "ii:blf.disable", &fontid, &option)) {
293     return NULL;
294   }
295
296   BLF_disable(fontid, option);
297
298   Py_RETURN_NONE;
299 }
300
301 PyDoc_STRVAR(py_blf_enable_doc,
302              ".. function:: enable(fontid, option)\n"
303              "\n"
304              "   Enable option.\n"
305              "\n"
306              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
307              "font use 0.\n"
308              "   :type fontid: int\n"
309              "   :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
310              "   :type option: int\n");
311 static PyObject *py_blf_enable(PyObject *UNUSED(self), PyObject *args)
312 {
313   int option, fontid;
314
315   if (!PyArg_ParseTuple(args, "ii:blf.enable", &fontid, &option)) {
316     return NULL;
317   }
318
319   BLF_enable(fontid, option);
320
321   Py_RETURN_NONE;
322 }
323
324 PyDoc_STRVAR(py_blf_rotation_doc,
325              ".. function:: rotation(fontid, angle)\n"
326              "\n"
327              "   Set the text rotation angle, enable/disable using ROTATION.\n"
328              "\n"
329              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
330              "font use 0.\n"
331              "   :type fontid: int\n"
332              "   :arg angle: The angle for text drawing to use.\n"
333              "   :type angle: float\n");
334 static PyObject *py_blf_rotation(PyObject *UNUSED(self), PyObject *args)
335 {
336   float angle;
337   int fontid;
338
339   if (!PyArg_ParseTuple(args, "if:blf.rotation", &fontid, &angle)) {
340     return NULL;
341   }
342
343   BLF_rotation(fontid, angle);
344
345   Py_RETURN_NONE;
346 }
347
348 PyDoc_STRVAR(py_blf_shadow_doc,
349              ".. function:: shadow(fontid, level, r, g, b, a)\n"
350              "\n"
351              "   Shadow options, enable/disable using SHADOW .\n"
352              "\n"
353              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
354              "font use 0.\n"
355              "   :type fontid: int\n"
356              "   :arg level: The blur level, can be 3, 5 or 0.\n"
357              "   :type level: int\n"
358              "   :arg r: Shadow color (red channel 0.0 - 1.0).\n"
359              "   :type r: float\n"
360              "   :arg g: Shadow color (green channel 0.0 - 1.0).\n"
361              "   :type g: float\n"
362              "   :arg b: Shadow color (blue channel 0.0 - 1.0).\n"
363              "   :type b: float\n"
364              "   :arg a: Shadow color (alpha channel 0.0 - 1.0).\n"
365              "   :type a: float\n");
366 static PyObject *py_blf_shadow(PyObject *UNUSED(self), PyObject *args)
367 {
368   int level, fontid;
369   float rgba[4];
370
371   if (!PyArg_ParseTuple(
372           args, "iiffff:blf.shadow", &fontid, &level, &rgba[0], &rgba[1], &rgba[2], &rgba[3])) {
373     return NULL;
374   }
375
376   if (!ELEM(level, 0, 3, 5)) {
377     PyErr_SetString(PyExc_TypeError, "blf.shadow expected arg to be in (0, 3, 5)");
378     return NULL;
379   }
380
381   BLF_shadow(fontid, level, rgba);
382
383   Py_RETURN_NONE;
384 }
385
386 PyDoc_STRVAR(py_blf_shadow_offset_doc,
387              ".. function:: shadow_offset(fontid, x, y)\n"
388              "\n"
389              "   Set the offset for shadow text.\n"
390              "\n"
391              "   :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
392              "font use 0.\n"
393              "   :type fontid: int\n"
394              "   :arg x: Vertical shadow offset value in pixels.\n"
395              "   :type x: float\n"
396              "   :arg y: Horizontal shadow offset value in pixels.\n"
397              "   :type y: float\n");
398 static PyObject *py_blf_shadow_offset(PyObject *UNUSED(self), PyObject *args)
399 {
400   int x, y, fontid;
401
402   if (!PyArg_ParseTuple(args, "iii:blf.shadow_offset", &fontid, &x, &y)) {
403     return NULL;
404   }
405
406   BLF_shadow_offset(fontid, x, y);
407
408   Py_RETURN_NONE;
409 }
410
411 PyDoc_STRVAR(py_blf_load_doc,
412              ".. function:: load(filename)\n"
413              "\n"
414              "   Load a new font.\n"
415              "\n"
416              "   :arg filename: the filename of the font.\n"
417              "   :type filename: string\n"
418              "   :return: the new font's fontid or -1 if there was an error.\n"
419              "   :rtype: integer\n");
420 static PyObject *py_blf_load(PyObject *UNUSED(self), PyObject *args)
421 {
422   const char *filename;
423
424   if (!PyArg_ParseTuple(args, "s:blf.load", &filename)) {
425     return NULL;
426   }
427
428   return PyLong_FromLong(BLF_load(filename));
429 }
430
431 PyDoc_STRVAR(py_blf_unload_doc,
432              ".. function:: unload(filename)\n"
433              "\n"
434              "   Unload an existing font.\n"
435              "\n"
436              "   :arg filename: the filename of the font.\n"
437              "   :type filename: string\n");
438 static PyObject *py_blf_unload(PyObject *UNUSED(self), PyObject *args)
439 {
440   const char *filename;
441
442   if (!PyArg_ParseTuple(args, "s:blf.unload", &filename)) {
443     return NULL;
444   }
445
446   BLF_unload(filename);
447
448   Py_RETURN_NONE;
449 }
450
451 /*----------------------------MODULE INIT-------------------------*/
452 static PyMethodDef BLF_methods[] = {
453     {"aspect", (PyCFunction)py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
454 #if BLF_BLUR_ENABLE
455     {"blur", (PyCFunction)py_blf_blur, METH_VARARGS, py_blf_blur_doc},
456 #endif
457     {"clipping", (PyCFunction)py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
458     {"word_wrap", (PyCFunction)py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
459     {"disable", (PyCFunction)py_blf_disable, METH_VARARGS, py_blf_disable_doc},
460     {"dimensions", (PyCFunction)py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
461     {"draw", (PyCFunction)py_blf_draw, METH_VARARGS, py_blf_draw_doc},
462     {"enable", (PyCFunction)py_blf_enable, METH_VARARGS, py_blf_enable_doc},
463     {"position", (PyCFunction)py_blf_position, METH_VARARGS, py_blf_position_doc},
464     {"rotation", (PyCFunction)py_blf_rotation, METH_VARARGS, py_blf_rotation_doc},
465     {"shadow", (PyCFunction)py_blf_shadow, METH_VARARGS, py_blf_shadow_doc},
466     {"shadow_offset", (PyCFunction)py_blf_shadow_offset, METH_VARARGS, py_blf_shadow_offset_doc},
467     {"size", (PyCFunction)py_blf_size, METH_VARARGS, py_blf_size_doc},
468     {"color", (PyCFunction)py_blf_color, METH_VARARGS, py_blf_color_doc},
469     {"load", (PyCFunction)py_blf_load, METH_VARARGS, py_blf_load_doc},
470     {"unload", (PyCFunction)py_blf_unload, METH_VARARGS, py_blf_unload_doc},
471     {NULL, NULL, 0, NULL},
472 };
473
474 PyDoc_STRVAR(BLF_doc, "This module provides access to Blender's text drawing functions.");
475 static struct PyModuleDef BLF_module_def = {
476     PyModuleDef_HEAD_INIT,
477     "blf",       /* m_name */
478     BLF_doc,     /* m_doc */
479     0,           /* m_size */
480     BLF_methods, /* m_methods */
481     NULL,        /* m_reload */
482     NULL,        /* m_traverse */
483     NULL,        /* m_clear */
484     NULL,        /* m_free */
485 };
486
487 PyObject *BPyInit_blf(void)
488 {
489   PyObject *submodule;
490
491   submodule = PyModule_Create(&BLF_module_def);
492
493   PyModule_AddIntConstant(submodule, "ROTATION", BLF_ROTATION);
494   PyModule_AddIntConstant(submodule, "CLIPPING", BLF_CLIPPING);
495   PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
496   PyModule_AddIntConstant(submodule, "KERNING_DEFAULT", BLF_KERNING_DEFAULT);
497   PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
498   PyModule_AddIntConstant(submodule, "MONOCHROME", BLF_MONOCHROME);
499
500   return submodule;
501 }