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