forked from adafruit/circuitpython
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPixelMap.c
More file actions
174 lines (148 loc) · 6.76 KB
/
PixelMap.c
File metadata and controls
174 lines (148 loc) · 6.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
* This file is part of the CircuitPython project, https://github.com/adafruit/circuitpython
*
* The MIT License (MIT)
*
* Copyright (c) 2018 Rose Hooper
* Copyright (c) 2022 Jeff Epler for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include "py/smallint.h"
#include "py/runtime.h"
#include "shared-bindings/_pixelmap/PixelMap.h"
#include "shared-bindings/adafruit_pixelbuf/PixelBuf.h"
#include "shared-module/_pixelmap/PixelMap.h"
static void pixelmap_set_pixel_rgbw(pixelmap_pixelmap_obj_t *self, size_t i, color_u rgbw) {
mp_arg_validate_index_range(i, 0, self->len - 1, MP_QSTR_index);
mp_obj_t item = self->items[i];
if (mp_obj_is_small_int(item)) {
common_hal_adafruit_pixelbuf_pixelbuf_set_pixel_color(self->pixelbuf, MP_OBJ_SMALL_INT_VALUE(item), rgbw.r, rgbw.g, rgbw.b, rgbw.w);
} else {
size_t len;
mp_obj_t *items;
mp_obj_tuple_get(item, &len, &items);
for (size_t j = 0; j < len; j++) {
common_hal_adafruit_pixelbuf_pixelbuf_set_pixel_color(self->pixelbuf, MP_OBJ_SMALL_INT_VALUE(items[j]), rgbw.r, rgbw.g, rgbw.b, rgbw.w);
}
}
}
static void pixelmap_set_pixel(pixelmap_pixelmap_obj_t *self, size_t i, mp_obj_t color) {
color_u rgbw;
common_hal_adafruit_pixelbuf_pixelbuf_parse_color(self->pixelbuf, color, &rgbw.r, &rgbw.g, &rgbw.b, &rgbw.w);
pixelmap_set_pixel_rgbw(self, i, rgbw);
}
void shared_module_pixelmap_pixelmap_construct(pixelmap_pixelmap_obj_t *self, mp_obj_t pixelbuf, mp_obj_t indices) {
self->pixelbuf = pixelbuf;
self->indices = indices;
mp_obj_tuple_get(indices, &self->len, &self->items);
}
static bool auto_write_get_and_clear(pixelmap_pixelmap_obj_t *self) {
bool auto_write = self->auto_write && common_hal_adafruit_pixelbuf_pixelbuf_get_auto_write(self->pixelbuf);
if (auto_write) {
common_hal_adafruit_pixelbuf_pixelbuf_set_auto_write(self->pixelbuf, false);
}
return auto_write;
}
static void auto_write_reapply(pixelmap_pixelmap_obj_t *self, bool auto_write) {
if (auto_write) {
common_hal_adafruit_pixelbuf_pixelbuf_set_auto_write(self->pixelbuf, true);
common_hal_adafruit_pixelbuf_pixelbuf_show(self->pixelbuf);
}
}
bool shared_module_pixelmap_pixelmap_auto_write_get(pixelmap_pixelmap_obj_t *self) {
return self->auto_write;
}
void shared_module_pixelmap_pixelmap_auto_write_set(pixelmap_pixelmap_obj_t *self, bool auto_write) {
self->auto_write = auto_write;
}
void shared_module_pixelmap_pixelmap_fill(pixelmap_pixelmap_obj_t *self, const mp_obj_t color) {
color_u rgbw;
common_hal_adafruit_pixelbuf_pixelbuf_parse_color(self->pixelbuf, color, &rgbw.r, &rgbw.g, &rgbw.b, &rgbw.w);
bool auto_write = auto_write_get_and_clear(self);
for (size_t i = 0; i < self->len; i++) {
pixelmap_set_pixel_rgbw(self, i, rgbw);
}
auto_write_reapply(self, auto_write);
}
mp_obj_t shared_module_pixelmap_pixelmap_indices(pixelmap_pixelmap_obj_t *self, int index) {
mp_arg_validate_index_range(index, 0, self->len - 1, MP_QSTR_index);
mp_obj_t item = self->items[index];
if (mp_obj_is_small_int(item)) {
return mp_obj_new_tuple(1, &item);
} else {
return item;
}
}
#if MICROPY_PY_BUILTINS_SLICE
mp_obj_t shared_module_pixelmap_pixelmap_getslice(pixelmap_pixelmap_obj_t *self, mp_bound_slice_t slice, size_t slice_len) {
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(slice_len, NULL));
for (uint i = 0; i < slice_len; i++) {
t->items[i] = shared_module_pixelmap_pixelmap_getitem(self, i * slice.step + slice.start);
}
return MP_OBJ_FROM_PTR(t);
}
void shared_module_pixelmap_pixelmap_setslice(pixelmap_pixelmap_obj_t *self, const mp_obj_t values, mp_bound_slice_t slice, size_t slice_len) {
size_t num_items = mp_obj_get_int(mp_obj_len(values));
if (num_items != slice_len) {
mp_raise_ValueError_varg(translate("Unmatched number of items on RHS (expected %d, got %d)."), slice_len, num_items);
}
bool auto_write = auto_write_get_and_clear(self);
// because we didn't preflight the pixel values, an exception could occur.
// In that case we need to do the auto-write of any pixels that were set
// before re-raising the exception
nlr_buf_t nlr;
size_t start = slice.start;
mp_int_t step = slice.step;
if (nlr_push(&nlr) == 0) {
mp_obj_iter_buf_t iter_buf;
mp_obj_t iterable = mp_getiter(values, &iter_buf);
mp_obj_t item;
while ((item = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
pixelmap_set_pixel(self, start, item);
start += step;
}
nlr_pop();
auto_write_reapply(self, auto_write);
} else {
auto_write_reapply(self, auto_write);
// exception converting color value, re-raise
nlr_raise(MP_OBJ_FROM_PTR(nlr.ret_val));
}
}
#endif
void shared_module_pixelmap_pixelmap_setitem(pixelmap_pixelmap_obj_t *self, mp_int_t i, mp_obj_t color) {
color_u rgbw;
common_hal_adafruit_pixelbuf_pixelbuf_parse_color(self->pixelbuf, color, &rgbw.r, &rgbw.g, &rgbw.b, &rgbw.w);
bool auto_write = auto_write_get_and_clear(self);
pixelmap_set_pixel_rgbw(self, i, rgbw);
auto_write_reapply(self, auto_write);
}
mp_obj_t shared_module_pixelmap_pixelmap_getitem(pixelmap_pixelmap_obj_t *self, mp_int_t i) {
mp_arg_validate_index_range(i, 0, self->len - 1, MP_QSTR_index);
mp_obj_t item = self->items[i];
if (mp_obj_is_small_int(item)) {
return common_hal_adafruit_pixelbuf_pixelbuf_get_pixel(self->pixelbuf, MP_OBJ_SMALL_INT_VALUE(item));
} else {
size_t len;
mp_obj_t *items;
mp_obj_tuple_get(item, &len, &items);
return common_hal_adafruit_pixelbuf_pixelbuf_get_pixel(self->pixelbuf, MP_OBJ_SMALL_INT_VALUE(items[0]));
}
}