Blender V5.0
blf_py_api.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11/* Future-proof, See https://docs.python.org/3/c-api/arg.html#strings-and-buffers */
12#define PY_SSIZE_T_CLEAN
13
14#include "blf_py_api.hh"
15
16#include "py_capi_utils.hh"
17
18#include <Python.h>
19
21
22#include "BLI_utildefines.h"
23
27
28#include "python_compat.hh" /* IWYU pragma: keep. */
29
30#include "python_utildefines.hh"
31
32#include "imbuf_py_api.hh"
33
35 PyObject_HEAD /* Required Python macro. */
36 PyObject *py_imbuf;
37
38 int fontid;
40};
41
43 /* Wrap. */
44 py_blf_position_doc,
45 ".. function:: position(fontid, x, y, z)\n"
46 "\n"
47 " Set the position for drawing text.\n"
48 "\n"
49 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
50 "font use 0.\n"
51 " :type fontid: int\n"
52 " :arg x: X axis position to draw the text.\n"
53 " :type x: float\n"
54 " :arg y: Y axis position to draw the text.\n"
55 " :type y: float\n"
56 " :arg z: Z axis position to draw the text.\n"
57 " :type z: float\n");
58static PyObject *py_blf_position(PyObject * /*self*/, PyObject *args)
59{
60 int fontid;
61 float x, y, z;
62
63 if (!PyArg_ParseTuple(args, "ifff:blf.position", &fontid, &x, &y, &z)) {
64 return nullptr;
65 }
66
67 BLF_position(fontid, x, y, z);
68
69 Py_RETURN_NONE;
70}
71
73 /* Wrap. */
74 py_blf_size_doc,
75 ".. function:: size(fontid, size)\n"
76 "\n"
77 " Set the size for drawing text.\n"
78 "\n"
79 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
80 "font use 0.\n"
81 " :type fontid: int\n"
82 " :arg size: Point size of the font.\n"
83 " :type size: float\n");
84static PyObject *py_blf_size(PyObject * /*self*/, PyObject *args)
85{
86 int fontid;
87 float size;
88
89 if (!PyArg_ParseTuple(args, "if:blf.size", &fontid, &size)) {
90 return nullptr;
91 }
92
93 BLF_size(fontid, size);
94
95 Py_RETURN_NONE;
96}
97
99 /* Wrap. */
100 py_blf_aspect_doc,
101 ".. function:: aspect(fontid, aspect)\n"
102 "\n"
103 " Set the aspect for drawing text.\n"
104 "\n"
105 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
106 "font use 0.\n"
107 " :type fontid: int\n"
108 " :arg aspect: The aspect ratio for text drawing to use.\n"
109 " :type aspect: float\n");
110static PyObject *py_blf_aspect(PyObject * /*self*/, PyObject *args)
111{
112 float aspect;
113 int fontid;
114
115 if (!PyArg_ParseTuple(args, "if:blf.aspect", &fontid, &aspect)) {
116 return nullptr;
117 }
118
119 BLF_aspect(fontid, aspect, aspect, 1.0);
120
121 Py_RETURN_NONE;
122}
123
125 /* Wrap. */
126 py_blf_color_doc,
127 ".. function:: color(fontid, r, g, b, a)\n"
128 "\n"
129 " Set the color for drawing text.\n"
130 "\n"
131 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
132 "font use 0.\n"
133 " :type fontid: int\n"
134 " :arg r: red channel 0.0 - 1.0.\n"
135 " :type r: float\n"
136 " :arg g: green channel 0.0 - 1.0.\n"
137 " :type g: float\n"
138 " :arg b: blue channel 0.0 - 1.0.\n"
139 " :type b: float\n"
140 " :arg a: alpha channel 0.0 - 1.0.\n"
141 " :type a: float\n");
142static PyObject *py_blf_color(PyObject * /*self*/, PyObject *args)
143{
144 int fontid;
145 float rgba[4];
146
147 if (!PyArg_ParseTuple(args, "iffff:blf.color", &fontid, &rgba[0], &rgba[1], &rgba[2], &rgba[3]))
148 {
149 return nullptr;
150 }
151
152 BLF_color4fv(fontid, rgba);
153
154 /* NOTE(@ideasman42): that storing these colors separately looks like something that could
155 * be refactored away if the font's internal color format was changed from `uint8` to `float`. */
156 BLF_buffer_col(fontid, rgba);
157
158 Py_RETURN_NONE;
159}
160
162 /* Wrap. */
163 py_blf_draw_doc,
164 ".. function:: draw(fontid, text)\n"
165 "\n"
166 " Draw text in the current context.\n"
167 "\n"
168 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
169 "font use 0.\n"
170 " :type fontid: int\n"
171 " :arg text: the text to draw.\n"
172 " :type text: str\n");
173static PyObject *py_blf_draw(PyObject * /*self*/, PyObject *args)
174{
175 const char *text;
176 Py_ssize_t text_length;
177 int fontid;
178
179 if (!PyArg_ParseTuple(args, "is#:blf.draw", &fontid, &text, &text_length)) {
180 return nullptr;
181 }
182
183 BLF_draw(fontid, text, uint(text_length));
184
185 Py_RETURN_NONE;
186}
187
189 /* Wrap. */
190 py_blf_draw_buffer_doc,
191 ".. function:: draw_buffer(fontid, text)\n"
192 "\n"
193 " Draw text into the buffer bound to the fontid.\n"
194 "\n"
195 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
196 "font use 0.\n"
197 " :type fontid: int\n"
198 " :arg text: the text to draw.\n"
199 " :type text: str\n");
200static PyObject *py_blf_draw_buffer(PyObject * /*self*/, PyObject *args)
201{
202 const char *text;
203 Py_ssize_t text_length;
204 int fontid;
205
206 if (!PyArg_ParseTuple(args, "is#:blf.draw_buffer", &fontid, &text, &text_length)) {
207 return nullptr;
208 }
209
210 BLF_draw_buffer(fontid, text, uint(text_length));
211
212 Py_RETURN_NONE;
213}
214
216 /* Wrap. */
217 py_blf_dimensions_doc,
218 ".. function:: dimensions(fontid, text)\n"
219 "\n"
220 " Return the width and height of the text.\n"
221 "\n"
222 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
223 "font use 0.\n"
224 " :type fontid: int\n"
225 " :arg text: the text to draw.\n"
226 " :type text: str\n"
227 " :return: the width and height of the text.\n"
228 " :rtype: tuple[float, float]\n");
229static PyObject *py_blf_dimensions(PyObject * /*self*/, PyObject *args)
230{
231 const char *text;
232 float width, height;
233 PyObject *ret;
234 int fontid;
235
236 if (!PyArg_ParseTuple(args, "is:blf.dimensions", &fontid, &text)) {
237 return nullptr;
238 }
239
240 BLF_width_and_height(fontid, text, INT_MAX, &width, &height);
241
242 ret = PyTuple_New(2);
243 PyTuple_SET_ITEMS(ret, PyFloat_FromDouble(width), PyFloat_FromDouble(height));
244 return ret;
245}
246
248 /* Wrap. */
249 py_blf_clipping_doc,
250 ".. function:: clipping(fontid, xmin, ymin, xmax, ymax)\n"
251 "\n"
252 " Set the clipping, enable/disable using CLIPPING.\n"
253 "\n"
254 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
255 "font use 0.\n"
256 " :type fontid: int\n"
257 " :arg xmin: Clip the drawing area by these bounds.\n"
258 " :type xmin: float\n"
259 " :arg ymin: Clip the drawing area by these bounds.\n"
260 " :type ymin: float\n"
261 " :arg xmax: Clip the drawing area by these bounds.\n"
262 " :type xmax: float\n"
263 " :arg ymax: Clip the drawing area by these bounds.\n"
264 " :type ymax: float\n");
265static PyObject *py_blf_clipping(PyObject * /*self*/, PyObject *args)
266{
267 float xmin, ymin, xmax, ymax;
268 int fontid;
269
270 if (!PyArg_ParseTuple(args, "iffff:blf.clipping", &fontid, &xmin, &ymin, &xmax, &ymax)) {
271 return nullptr;
272 }
273
274 BLF_clipping(fontid, xmin, ymin, xmax, ymax);
275
276 Py_RETURN_NONE;
277}
278
280 /* Wrap. */
281 py_blf_word_wrap_doc,
282 ".. function:: word_wrap(fontid, wrap_width)\n"
283 "\n"
284 " Set the wrap width, enable/disable using WORD_WRAP.\n"
285 "\n"
286 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
287 "font use 0.\n"
288 " :type fontid: int\n"
289 " :arg wrap_width: The width (in pixels) to wrap words at.\n"
290 " :type wrap_width: int\n");
291static PyObject *py_blf_word_wrap(PyObject * /*self*/, PyObject *args)
292{
293 int wrap_width;
294 int fontid;
295
296 if (!PyArg_ParseTuple(args, "ii:blf.word_wrap", &fontid, &wrap_width)) {
297 return nullptr;
298 }
299
300 BLF_wordwrap(fontid, wrap_width);
301
302 Py_RETURN_NONE;
303}
304
306 /* Wrap. */
307 py_blf_disable_doc,
308 ".. function:: disable(fontid, option)\n"
309 "\n"
310 " Disable option.\n"
311 "\n"
312 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
313 "font use 0.\n"
314 " :type fontid: int\n"
315 " :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
316 " :type option: int\n");
317static PyObject *py_blf_disable(PyObject * /*self*/, PyObject *args)
318{
319 int option, fontid;
320
321 if (!PyArg_ParseTuple(args, "ii:blf.disable", &fontid, &option)) {
322 return nullptr;
323 }
324
325 BLF_disable(fontid, FontFlags(option));
326
327 Py_RETURN_NONE;
328}
329
331 /* Wrap. */
332 py_blf_enable_doc,
333 ".. function:: enable(fontid, option)\n"
334 "\n"
335 " Enable option.\n"
336 "\n"
337 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
338 "font use 0.\n"
339 " :type fontid: int\n"
340 " :arg option: One of ROTATION, CLIPPING, SHADOW or KERNING_DEFAULT.\n"
341 " :type option: int\n");
342static PyObject *py_blf_enable(PyObject * /*self*/, PyObject *args)
343{
344 int option, fontid;
345
346 if (!PyArg_ParseTuple(args, "ii:blf.enable", &fontid, &option)) {
347 return nullptr;
348 }
349
350 BLF_enable(fontid, FontFlags(option));
351
352 Py_RETURN_NONE;
353}
354
356 /* Wrap. */
357 py_blf_rotation_doc,
358 ".. function:: rotation(fontid, angle)\n"
359 "\n"
360 " Set the text rotation angle, enable/disable using ROTATION.\n"
361 "\n"
362 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
363 "font use 0.\n"
364 " :type fontid: int\n"
365 " :arg angle: The angle for text drawing to use.\n"
366 " :type angle: float\n");
367static PyObject *py_blf_rotation(PyObject * /*self*/, PyObject *args)
368{
369 float angle;
370 int fontid;
371
372 if (!PyArg_ParseTuple(args, "if:blf.rotation", &fontid, &angle)) {
373 return nullptr;
374 }
375
376 BLF_rotation(fontid, angle);
377
378 Py_RETURN_NONE;
379}
380
382 /* Wrap. */
383 py_blf_shadow_doc,
384 ".. function:: shadow(fontid, level, r, g, b, a)\n"
385 "\n"
386 " Shadow options, enable/disable using SHADOW .\n"
387 "\n"
388 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
389 "font use 0.\n"
390 " :type fontid: int\n"
391 " :arg level: The blur level (0, 3, 5) or outline (6).\n"
392 " :type level: int\n"
393 " :arg r: Shadow color (red channel 0.0 - 1.0).\n"
394 " :type r: float\n"
395 " :arg g: Shadow color (green channel 0.0 - 1.0).\n"
396 " :type g: float\n"
397 " :arg b: Shadow color (blue channel 0.0 - 1.0).\n"
398 " :type b: float\n"
399 " :arg a: Shadow color (alpha channel 0.0 - 1.0).\n"
400 " :type a: float\n");
401static PyObject *py_blf_shadow(PyObject * /*self*/, PyObject *args)
402{
403 int level, fontid;
404 float rgba[4];
405
406 if (!PyArg_ParseTuple(
407 args, "iiffff:blf.shadow", &fontid, &level, &rgba[0], &rgba[1], &rgba[2], &rgba[3]))
408 {
409 return nullptr;
410 }
411
412 if (!ELEM(level, 0, 3, 5, 6)) {
413 PyErr_SetString(PyExc_TypeError, "blf.shadow expected arg to be in (0, 3, 5, 6)");
414 return nullptr;
415 }
416
417 BLF_shadow(fontid, FontShadowType(level), rgba);
418
419 Py_RETURN_NONE;
420}
421
423 /* Wrap. */
424 py_blf_shadow_offset_doc,
425 ".. function:: shadow_offset(fontid, x, y)\n"
426 "\n"
427 " Set the offset for shadow text.\n"
428 "\n"
429 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
430 "font use 0.\n"
431 " :type fontid: int\n"
432 " :arg x: Vertical shadow offset value in pixels.\n"
433 " :type x: float\n"
434 " :arg y: Horizontal shadow offset value in pixels.\n"
435 " :type y: float\n");
436static PyObject *py_blf_shadow_offset(PyObject * /*self*/, PyObject *args)
437{
438 int x, y, fontid;
439
440 if (!PyArg_ParseTuple(args, "iii:blf.shadow_offset", &fontid, &x, &y)) {
441 return nullptr;
442 }
443
444 BLF_shadow_offset(fontid, x, y);
445
446 Py_RETURN_NONE;
447}
448
450 /* Wrap. */
451 py_blf_load_doc,
452 ".. function:: load(filepath)\n"
453 "\n"
454 " Load a new font.\n"
455 "\n"
456 " :arg filepath: the filepath of the font.\n"
457 " :type filepath: str | bytes\n"
458 " :return: the new font's fontid or -1 if there was an error.\n"
459 " :rtype: int\n");
460static PyObject *py_blf_load(PyObject * /*self*/, PyObject *args)
461{
462 PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
463 if (!PyArg_ParseTuple(args,
464 "O&" /* `filepath` */
465 ":blf.load",
467 &filepath_data))
468 {
469 return nullptr;
470 }
471 const int font_id = BLF_load(filepath_data.value);
472 Py_XDECREF(filepath_data.value_coerce);
473
474 return PyLong_FromLong(font_id);
475}
476
478 /* Wrap. */
479 py_blf_unload_doc,
480 ".. function:: unload(filepath)\n"
481 "\n"
482 " Unload an existing font.\n"
483 "\n"
484 " :arg filepath: the filepath of the font.\n"
485 " :type filepath: str | bytes\n");
486static PyObject *py_blf_unload(PyObject * /*self*/, PyObject *args)
487{
488 PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
489 if (!PyArg_ParseTuple(args,
490 "O&" /* `filepath` */
491 ":blf.unload",
493 &filepath_data))
494 {
495 return nullptr;
496 }
497
498 BLF_unload(filepath_data.value);
499 Py_XDECREF(filepath_data.value_coerce);
500
501 Py_RETURN_NONE;
502}
503
504/* -------------------------------------------------------------------- */
509
511{
512 if (UNLIKELY(self->buffer_state)) {
513 PyErr_SetString(PyExc_ValueError,
514 "BLFImBufContext.__enter__: unable to enter the same context more than once");
515 return nullptr;
516 }
517
518 ImBuf *ibuf = BPy_ImBuf_FromPyObject(self->py_imbuf);
519 if (ibuf == nullptr) {
520 /* The error will have been set. */
521 return nullptr;
522 }
523 BLFBufferState *buffer_state = BLF_buffer_state_push(self->fontid);
524 if (buffer_state == nullptr) {
525 PyErr_Format(PyExc_ValueError, "bind_imbuf: unknown fontid %d", self->fontid);
526 return nullptr;
527 }
528 BLF_buffer(self->fontid,
529 ibuf->float_buffer.data,
530 ibuf->byte_buffer.data,
531 ibuf->x,
532 ibuf->y,
533 ibuf->byte_buffer.colorspace);
534 self->buffer_state = buffer_state;
535
536 Py_RETURN_NONE;
537}
538
539static PyObject *py_blf_bind_imbuf_exit(BPyBLFImBufContext *self, PyObject * /*args*/)
540{
541 BLF_buffer_state_pop(self->buffer_state);
542 self->buffer_state = nullptr;
543
544 Py_RETURN_NONE;
545}
546
548{
549 if (self->buffer_state) {
550 /* This should practically never happen since it implies
551 * `__enter__` is called without a matching `__exit__`.
552 * Do this mainly for correctness:
553 * if the process somehow exits before exiting the context manager. */
554 BLF_buffer_state_free(self->buffer_state);
555 }
556
557 PyObject_GC_UnTrack(self);
558 Py_CLEAR(self->py_imbuf);
559 PyObject_GC_Del(self);
560}
561
562static int py_blf_bind_imbuf_traverse(BPyBLFImBufContext *self, visitproc visit, void *arg)
563{
564 Py_VISIT(self->py_imbuf);
565 return 0;
566}
567
569{
570 Py_CLEAR(self->py_imbuf);
571 return 0;
572}
573
574#ifdef __GNUC__
575# ifdef __clang__
576# pragma clang diagnostic push
577# pragma clang diagnostic ignored "-Wcast-function-type"
578# else
579# pragma GCC diagnostic push
580# pragma GCC diagnostic ignored "-Wcast-function-type"
581# endif
582#endif
583
584static PyMethodDef py_blf_bind_imbuf_methods[] = {
585 {"__enter__", (PyCFunction)py_blf_bind_imbuf_enter, METH_NOARGS},
586 {"__exit__", (PyCFunction)py_blf_bind_imbuf_exit, METH_VARARGS},
587 {nullptr},
588};
589
590#ifdef __GNUC__
591# ifdef __clang__
592# pragma clang diagnostic pop
593# else
594# pragma GCC diagnostic pop
595# endif
596#endif
597
598static PyTypeObject BPyBLFImBufContext_Type = {
599 /*ob_base*/ PyVarObject_HEAD_INIT(nullptr, 0)
600 /*tp_name*/ "BLFImBufContext",
601 /*tp_basicsize*/ sizeof(BPyBLFImBufContext),
602 /*tp_itemsize*/ 0,
603 /*tp_dealloc*/ (destructor)py_blf_bind_imbuf_dealloc,
604 /*tp_vectorcall_offset*/ 0,
605 /*tp_getattr*/ nullptr,
606 /*tp_setattr*/ nullptr,
607 /*tp_as_async*/ nullptr,
608 /*tp_repr*/ nullptr,
609 /*tp_as_number*/ nullptr,
610 /*tp_as_sequence*/ nullptr,
611 /*tp_as_mapping*/ nullptr,
612 /*tp_hash*/ nullptr,
613 /*tp_call*/ nullptr,
614 /*tp_str*/ nullptr,
615 /*tp_getattro*/ nullptr,
616 /*tp_setattro*/ nullptr,
617 /*tp_as_buffer*/ nullptr,
618 /*tp_flags*/ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
619 /*tp_doc*/ nullptr,
620 /*tp_traverse*/ (traverseproc)py_blf_bind_imbuf_traverse,
621 /*tp_clear*/ (inquiry)py_blf_bind_imbuf_clear,
622 /*tp_richcompare*/ nullptr,
623 /*tp_weaklistoffset*/ 0,
624 /*tp_iter*/ nullptr,
625 /*tp_iternext*/ nullptr,
626 /*tp_methods*/ py_blf_bind_imbuf_methods,
627 /*tp_members*/ nullptr,
628 /*tp_getset*/ nullptr,
629 /*tp_base*/ nullptr,
630 /*tp_dict*/ nullptr,
631 /*tp_descr_get*/ nullptr,
632 /*tp_descr_set*/ nullptr,
633 /*tp_dictoffset*/ 0,
634 /*tp_init*/ nullptr,
635 /*tp_alloc*/ nullptr,
636 /*tp_new*/ nullptr,
637 /*tp_free*/ nullptr,
638 /*tp_is_gc*/ nullptr,
639 /*tp_bases*/ nullptr,
640 /*tp_mro*/ nullptr,
641 /*tp_cache*/ nullptr,
642 /*tp_subclasses*/ nullptr,
643 /*tp_weaklist*/ nullptr,
644 /*tp_del*/ nullptr,
645 /*tp_version_tag*/ 0,
646 /*tp_finalize*/ nullptr,
647 /*tp_vectorcall*/ nullptr,
648};
649
650/* NOTE(@ideasman42): `BLFImBufContext` isn't accessible from (without creating an instance),
651 * it should be exposed although it doesn't seem especially important either. */
653 /* Wrap. */
654 py_blf_bind_imbuf_doc,
655 ".. method:: bind_imbuf(fontid, image)\n"
656 "\n"
657 " Context manager to draw text into an image buffer instead of the GPU's context.\n"
658 "\n"
659 " :arg fontid: The id of the typeface as returned by :func:`blf.load`, for default "
660 "font use 0.\n"
661 " :type fontid: int\n"
662 " :arg imbuf: The image to draw into.\n"
663 " :type imbuf: :class:`imbuf.types.ImBuf`\n"
664
665 " :return: The BLF ImBuf context manager.\n"
666 " :rtype: BLFImBufContext\n");
667static PyObject *py_blf_bind_imbuf(PyObject * /*self*/, PyObject *args, PyObject *kwds)
668{
669 int fontid;
670 PyObject *py_imbuf = nullptr;
671 const char *display_name = nullptr;
672
673 static const char *_keywords[] = {
674 "",
675 "",
676 "display_name",
677 nullptr,
678 };
679
680 static _PyArg_Parser _parser = {
682 "i" /* `fontid` */
683 "O!" /* `image` */
684 "|" /* Optional arguments. */
685 "z" /* `display_name` */
686 ":bind_imbuf",
687 _keywords,
688 nullptr,
689 };
690 if (!_PyArg_ParseTupleAndKeywordsFast(
691 args, kwds, &_parser, &fontid, &Py_ImBuf_Type, &py_imbuf, &display_name))
692 {
693 return nullptr;
694 }
695
696 /* Display name is ignored, it is only kept for backwards compatibility. This should
697 * always have been the image buffer byte colorspace rather than a display. */
698
700
701 ret->py_imbuf = Py_NewRef(py_imbuf);
702
703 ret->fontid = fontid;
704 ret->buffer_state = nullptr;
705
706 PyObject_GC_Track(ret);
707
708 return (PyObject *)ret;
709}
710
712
713#ifdef __GNUC__
714# ifdef __clang__
715# pragma clang diagnostic push
716# pragma clang diagnostic ignored "-Wcast-function-type"
717# else
718# pragma GCC diagnostic push
719# pragma GCC diagnostic ignored "-Wcast-function-type"
720# endif
721#endif
722
723/*----------------------------MODULE INIT-------------------------*/
724static PyMethodDef BLF_methods[] = {
725 {"aspect", (PyCFunction)py_blf_aspect, METH_VARARGS, py_blf_aspect_doc},
726 {"clipping", (PyCFunction)py_blf_clipping, METH_VARARGS, py_blf_clipping_doc},
727 {"word_wrap", (PyCFunction)py_blf_word_wrap, METH_VARARGS, py_blf_word_wrap_doc},
728 {"disable", (PyCFunction)py_blf_disable, METH_VARARGS, py_blf_disable_doc},
729 {"dimensions", (PyCFunction)py_blf_dimensions, METH_VARARGS, py_blf_dimensions_doc},
730 {"draw", (PyCFunction)py_blf_draw, METH_VARARGS, py_blf_draw_doc},
731 {"draw_buffer", (PyCFunction)py_blf_draw_buffer, METH_VARARGS, py_blf_draw_buffer_doc},
732 {"enable", (PyCFunction)py_blf_enable, METH_VARARGS, py_blf_enable_doc},
733 {"position", (PyCFunction)py_blf_position, METH_VARARGS, py_blf_position_doc},
734 {"rotation", (PyCFunction)py_blf_rotation, METH_VARARGS, py_blf_rotation_doc},
735 {"shadow", (PyCFunction)py_blf_shadow, METH_VARARGS, py_blf_shadow_doc},
736 {"shadow_offset", (PyCFunction)py_blf_shadow_offset, METH_VARARGS, py_blf_shadow_offset_doc},
737 {"size", (PyCFunction)py_blf_size, METH_VARARGS, py_blf_size_doc},
738 {"color", (PyCFunction)py_blf_color, METH_VARARGS, py_blf_color_doc},
739 {"load", (PyCFunction)py_blf_load, METH_VARARGS, py_blf_load_doc},
740 {"unload", (PyCFunction)py_blf_unload, METH_VARARGS, py_blf_unload_doc},
741
742 {"bind_imbuf",
743 (PyCFunction)py_blf_bind_imbuf,
744 METH_VARARGS | METH_KEYWORDS,
745 py_blf_bind_imbuf_doc},
746
747 {nullptr, nullptr, 0, nullptr},
748};
749
750#ifdef __GNUC__
751# ifdef __clang__
752# pragma clang diagnostic pop
753# else
754# pragma GCC diagnostic pop
755# endif
756#endif
757
759 /* Wrap. */
760 BLF_doc,
761 "This module provides access to Blender's text drawing functions.");
762static PyModuleDef BLF_module_def = {
763 /*m_base*/ PyModuleDef_HEAD_INIT,
764 /*m_name*/ "blf",
765 /*m_doc*/ BLF_doc,
766 /*m_size*/ 0,
767 /*m_methods*/ BLF_methods,
768 /*m_slots*/ nullptr,
769 /*m_traverse*/ nullptr,
770 /*m_clear*/ nullptr,
771 /*m_free*/ nullptr,
772};
773
774PyObject *BPyInit_blf()
775{
776 PyObject *submodule;
777
778 submodule = PyModule_Create(&BLF_module_def);
779
780 PyModule_AddIntConstant(submodule, "ROTATION", BLF_ROTATION);
781 PyModule_AddIntConstant(submodule, "CLIPPING", BLF_CLIPPING);
782 PyModule_AddIntConstant(submodule, "SHADOW", BLF_SHADOW);
783 PyModule_AddIntConstant(submodule, "WORD_WRAP", BLF_WORD_WRAP);
784 PyModule_AddIntConstant(submodule, "MONOCHROME", BLF_MONOCHROME);
785
786 return submodule;
787}
void BLF_size(int fontid, float size)
Definition blf.cc:443
void BLF_buffer_state_free(BLFBufferState *buffer_state)
Definition blf.cc:1010
void BLF_enable(int fontid, FontFlags flag)
Definition blf.cc:320
void BLF_buffer_state_pop(BLFBufferState *buffer_state)
Definition blf.cc:993
void BLF_shadow(int fontid, FontShadowType type, const float rgba[4]=nullptr)
Definition blf.cc:934
void BLF_aspect(int fontid, float x, float y, float z)
Definition blf.cc:377
void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, const ColorSpace *colorspace)
Definition blf.cc:956
void BLF_clipping(int fontid, int xmin, int ymin, int xmax, int ymax)
Definition blf.cc:912
void BLF_draw_buffer(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:1045
void BLF_width_and_height(int fontid, const char *str, size_t str_len, float *r_width, float *r_height) ATTR_NONNULL()
Definition blf.cc:789
void BLF_color4fv(int fontid, const float rgba[4])
Definition blf.cc:505
void BLF_shadow_offset(int fontid, int x, int y)
Definition blf.cc:946
BLFBufferState * BLF_buffer_state_push(int fontid)
Definition blf.cc:980
void BLF_rotation(int fontid, float angle)
Definition blf.cc:903
void BLF_draw(int fontid, const char *str, size_t str_len, ResultBLF *r_info=nullptr) ATTR_NONNULL(2)
Definition blf.cc:585
void BLF_wordwrap(int fontid, int wrap_width, BLFWrapMode mode=BLFWrapMode::Minimal)
Definition blf.cc:924
int BLF_load(const char *filepath) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition blf.cc:175
void BLF_buffer_col(int fontid, const float srgb_color[4]) ATTR_NONNULL(2)
Definition blf.cc:1015
void BLF_disable(int fontid, FontFlags flag)
Definition blf.cc:329
int void BLF_unload(const char *filepath) ATTR_NONNULL(1)
Definition blf.cc:259
void BLF_position(int fontid, float x, float y, float z)
Definition blf.cc:388
FontFlags
Definition BLF_enums.hh:31
@ BLF_ROTATION
Definition BLF_enums.hh:33
@ BLF_WORD_WRAP
Definition BLF_enums.hh:39
@ BLF_MONOCHROME
Definition BLF_enums.hh:41
@ BLF_SHADOW
Definition BLF_enums.hh:35
@ BLF_CLIPPING
Definition BLF_enums.hh:34
FontShadowType
Definition BLF_enums.hh:13
unsigned int uint
#define UNLIKELY(x)
#define ELEM(...)
static double angle(const Eigen::Vector3d &v1, const Eigen::Vector3d &v2)
Definition IK_Math.h:117
static PyObject * py_blf_word_wrap(PyObject *, PyObject *args)
static int py_blf_bind_imbuf_clear(BPyBLFImBufContext *self)
static int py_blf_bind_imbuf_traverse(BPyBLFImBufContext *self, visitproc visit, void *arg)
PyObject * BPyInit_blf()
static PyObject * py_blf_enable(PyObject *, PyObject *args)
static PyObject * py_blf_aspect(PyObject *, PyObject *args)
static PyModuleDef BLF_module_def
static PyObject * py_blf_color(PyObject *, PyObject *args)
static PyObject * py_blf_shadow_offset(PyObject *, PyObject *args)
static PyMethodDef BLF_methods[]
static PyObject * py_blf_unload(PyObject *, PyObject *args)
static void py_blf_bind_imbuf_dealloc(BPyBLFImBufContext *self)
static PyObject * py_blf_bind_imbuf_exit(BPyBLFImBufContext *self, PyObject *)
static PyTypeObject BPyBLFImBufContext_Type
static PyObject * py_blf_load(PyObject *, PyObject *args)
static PyObject * py_blf_shadow(PyObject *, PyObject *args)
static PyObject * py_blf_dimensions(PyObject *, PyObject *args)
static PyObject * py_blf_clipping(PyObject *, PyObject *args)
static PyObject * py_blf_bind_imbuf_enter(BPyBLFImBufContext *self)
static PyObject * py_blf_rotation(PyObject *, PyObject *args)
static PyObject * py_blf_draw_buffer(PyObject *, PyObject *args)
static PyObject * py_blf_bind_imbuf(PyObject *, PyObject *args, PyObject *kwds)
static PyObject * py_blf_disable(PyObject *, PyObject *args)
static PyObject * py_blf_draw(PyObject *, PyObject *args)
static PyObject * py_blf_size(PyObject *, PyObject *args)
Definition blf_py_api.cc:84
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 *, PyObject *args)
Definition blf_py_api.cc:58
static PyMethodDef py_blf_bind_imbuf_methods[]
PyObject * self
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
SIMD_FORCE_INLINE const btScalar & z() const
Return the z value.
Definition btQuadWord.h:117
PyTypeObject Py_ImBuf_Type
ImBuf * BPy_ImBuf_FromPyObject(PyObject *py_imbuf)
int PyC_ParseUnicodeAsBytesAndSize(PyObject *o, void *p)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
header-only utilities
#define PyTuple_SET_ITEMS(op_arg,...)
return ret
BLFBufferState * buffer_state
Definition blf_py_api.cc:39
PyObject_HEAD PyObject * py_imbuf
Definition blf_py_api.cc:36
const ColorSpace * colorspace
ImBufFloatBuffer float_buffer
ImBufByteBuffer byte_buffer