Blender V5.0
bpy_app_icons.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#include <Python.h>
12
13#include "MEM_guardedalloc.h"
14
15#include "BKE_icons.h"
16
18#include "../generic/python_compat.hh" /* IWYU pragma: keep. */
19
20#include "bpy_app_icons.hh"
21
22/* We may want to load direct from file. */
24 /* Wrap. */
25 bpy_app_icons_new_triangles_doc,
26 ".. function:: new_triangles(range, coords, colors)\n"
27 "\n"
28 " Create a new icon from triangle geometry.\n"
29 "\n"
30 " :arg range: Pair of ints.\n"
31 " :type range: tuple[int, int]\n"
32 " :arg coords: Sequence of bytes (6 floats for one triangle) for (X, Y) coordinates.\n"
33 " :type coords: bytes\n"
34 " :arg colors: Sequence of bytes (12 for one triangles) for RGBA.\n"
35 " :type colors: bytes\n"
36 " :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
37 " :rtype: int\n");
38static PyObject *bpy_app_icons_new_triangles(PyObject * /*self*/, PyObject *args, PyObject *kw)
39{
40 /* bytes */
41 uchar coords_range[2];
42 PyObject *py_coords, *py_colors;
43
44 static const char *_keywords[] = {"range", "coords", "colors", nullptr};
45 static _PyArg_Parser _parser = {
47 "(BB)" /* `range` */
48 "S" /* `coords` */
49 "S" /* `colors` */
50 ":new_triangles",
51 _keywords,
52 nullptr,
53 };
54 if (!_PyArg_ParseTupleAndKeywordsFast(
55 args, kw, &_parser, &coords_range[0], &coords_range[1], &py_coords, &py_colors))
56 {
57 return nullptr;
58 }
59
60 const int coords_len = PyBytes_GET_SIZE(py_coords);
61 const int tris_len = coords_len / 6;
62 if (tris_len * 6 != coords_len) {
63 PyErr_SetString(PyExc_ValueError, "coords must be multiple of 6");
64 return nullptr;
65 }
66 if (PyBytes_GET_SIZE(py_colors) != 2 * coords_len) {
67 PyErr_SetString(PyExc_ValueError, "colors must be twice size of coords");
68 return nullptr;
69 }
70
71 const size_t items_num = size_t(tris_len) * 3;
72 uchar(*coords)[2] = MEM_malloc_arrayN<uchar[2]>(items_num, __func__);
73 uchar(*colors)[4] = MEM_malloc_arrayN<uchar[4]>(items_num, __func__);
74
75 memcpy(coords, PyBytes_AS_STRING(py_coords), sizeof(*coords) * items_num);
76 memcpy(colors, PyBytes_AS_STRING(py_colors), sizeof(*colors) * items_num);
77
78 Icon_Geom *geom = MEM_mallocN<Icon_Geom>(__func__);
79 geom->coords_len = tris_len;
80 geom->coords_range[0] = coords_range[0];
81 geom->coords_range[1] = coords_range[1];
82 geom->coords = coords;
83 geom->colors = colors;
84 geom->icon_id = 0;
85 const int icon_id = BKE_icon_geom_ensure(geom);
86 return PyLong_FromLong(icon_id);
87}
88
90 /* Wrap. */
91 bpy_app_icons_new_triangles_from_file_doc,
92 ".. function:: new_triangles_from_file(filepath)\n"
93 "\n"
94 " Create a new icon from triangle geometry.\n"
95 "\n"
96 " :arg filepath: File path.\n"
97 " :type filepath: str | bytes.\n"
98 " :return: Unique icon value (pass to interface ``icon_value`` argument).\n"
99 " :rtype: int\n");
100static PyObject *bpy_app_icons_new_triangles_from_file(PyObject * /*self*/,
101 PyObject *args,
102 PyObject *kw)
103{
104 PyC_UnicodeAsBytesAndSize_Data filepath_data = {nullptr};
105
106 static const char *_keywords[] = {"filepath", nullptr};
107 static _PyArg_Parser _parser = {
109 "O&" /* `filepath` */
110 ":new_triangles_from_file",
111 _keywords,
112 nullptr,
113 };
114 if (!_PyArg_ParseTupleAndKeywordsFast(
115 args, kw, &_parser, PyC_ParseUnicodeAsBytesAndSize, &filepath_data))
116 {
117 return nullptr;
118 }
119
120 Icon_Geom *geom = BKE_icon_geom_from_file(filepath_data.value);
121 Py_XDECREF(filepath_data.value_coerce);
122
123 if (geom == nullptr) {
124 PyErr_SetString(PyExc_ValueError, "Unable to load from file");
125 return nullptr;
126 }
127 const int icon_id = BKE_icon_geom_ensure(geom);
128 return PyLong_FromLong(icon_id);
129}
130
132 /* Wrap. */
133 bpy_app_icons_release_doc,
134 ".. function:: release(icon_id)\n"
135 "\n"
136 " Release the icon.\n");
137static PyObject *bpy_app_icons_release(PyObject * /*self*/, PyObject *args, PyObject *kw)
138{
139 int icon_id;
140 static const char *_keywords[] = {"icon_id", nullptr};
141 static _PyArg_Parser _parser = {
143 "i" /* `icon_id` */
144 ":release",
145 _keywords,
146 nullptr,
147 };
148 if (!_PyArg_ParseTupleAndKeywordsFast(args, kw, &_parser, &icon_id)) {
149 return nullptr;
150 }
151
152 if (!BKE_icon_delete_unmanaged(icon_id)) {
153 PyErr_SetString(PyExc_ValueError, "invalid icon_id");
154 return nullptr;
155 }
156 Py_RETURN_NONE;
157}
158
159#ifdef __GNUC__
160# ifdef __clang__
161# pragma clang diagnostic push
162# pragma clang diagnostic ignored "-Wcast-function-type"
163# else
164# pragma GCC diagnostic push
165# pragma GCC diagnostic ignored "-Wcast-function-type"
166# endif
167#endif
168
169static PyMethodDef M_AppIcons_methods[] = {
170 {"new_triangles",
171 (PyCFunction)bpy_app_icons_new_triangles,
172 METH_VARARGS | METH_KEYWORDS,
173 bpy_app_icons_new_triangles_doc},
174 {"new_triangles_from_file",
176 METH_VARARGS | METH_KEYWORDS,
177 bpy_app_icons_new_triangles_from_file_doc},
178 {"release",
179 (PyCFunction)bpy_app_icons_release,
180 METH_VARARGS | METH_KEYWORDS,
181 bpy_app_icons_release_doc},
182 {nullptr, nullptr, 0, nullptr},
183};
184
185#ifdef __GNUC__
186# ifdef __clang__
187# pragma clang diagnostic pop
188# else
189# pragma GCC diagnostic pop
190# endif
191#endif
192
193static PyModuleDef M_AppIcons_module_def = {
194 /*m_base*/ PyModuleDef_HEAD_INIT,
195 /*m_name*/ "bpy.app.icons",
196 /*m_doc*/ nullptr,
197 /*m_size*/ 0,
198 /*m_methods*/ M_AppIcons_methods,
199 /*m_slots*/ nullptr,
200 /*m_traverse*/ nullptr,
201 /*m_clear*/ nullptr,
202 /*m_free*/ nullptr,
203};
204
206{
207 PyObject *sys_modules = PyImport_GetModuleDict();
208
209 PyObject *mod = PyModule_Create(&M_AppIcons_module_def);
210
211 PyDict_SetItem(sys_modules, PyModule_GetNameObject(mod), mod);
212
213 return mod;
214}
bool BKE_icon_delete_unmanaged(int icon_id)
Definition icons.cc:472
int BKE_icon_geom_ensure(struct Icon_Geom *geom)
Definition icons.cc:500
struct Icon_Geom * BKE_icon_geom_from_file(const char *filename)
Definition icons.cc:555
unsigned char uchar
Read Guarded memory(de)allocation.
static PyObject * bpy_app_icons_new_triangles(PyObject *, PyObject *args, PyObject *kw)
PyObject * BPY_app_icons_module()
static PyModuleDef M_AppIcons_module_def
PyDoc_STRVAR(bpy_app_icons_new_triangles_doc, ".. function:: new_triangles(range, coords, colors)\n" "\n" " Create a new icon from triangle geometry.\n" "\n" " :arg range: Pair of ints.\n" " :type range: tuple[int, int]\n" " :arg coords: Sequence of bytes (6 floats for one triangle) for (X, Y) coordinates.\n" " :type coords: bytes\n" " :arg colors: Sequence of bytes (12 for one triangles) for RGBA.\n" " :type colors: bytes\n" " :return: Unique icon value (pass to interface ``icon_value`` argument).\n" " :rtype: int\n")
static PyObject * bpy_app_icons_release(PyObject *, PyObject *args, PyObject *kw)
static PyMethodDef M_AppIcons_methods[]
static PyObject * bpy_app_icons_new_triangles_from_file(PyObject *, PyObject *args, PyObject *kw)
VecBase< float, D > constexpr mod(VecOp< float, D >, VecOp< float, D >) RET
void * MEM_mallocN(size_t len, const char *str)
Definition mallocn.cc:128
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
int PyC_ParseUnicodeAsBytesAndSize(PyObject *o, void *p)
header-only compatibility defines.
#define PY_ARG_PARSER_HEAD_COMPAT()
int coords_len
Definition BKE_icons.h:60
unsigned char(* colors)[4]
Definition BKE_icons.h:63
int icon_id
Definition BKE_icons.h:59
unsigned char(* coords)[2]
Definition BKE_icons.h:62
int coords_range[2]
Definition BKE_icons.h:61