Skip to content

Commit 6fcda1d

Browse files
committed
Support multi-byte values with Bitmap
It also corrects the behavior of single byte values. Fixes adafruit#1744
1 parent 5b0c1c8 commit 6fcda1d

File tree

4 files changed

+39
-45
lines changed

4 files changed

+39
-45
lines changed

shared-module/displayio/Bitmap.c

Lines changed: 33 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,21 @@
3333
void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t width,
3434
uint32_t height, uint32_t bits_per_value) {
3535
uint32_t row_width = width * bits_per_value;
36-
// word align
37-
if (row_width % 32 != 0) {
38-
self->stride = (row_width / 32 + 1);
36+
// align to size_t
37+
uint8_t align_bits = 8 * sizeof(size_t);
38+
if (row_width % align_bits != 0) {
39+
self->stride = (row_width / align_bits + 1);
3940
} else {
40-
self->stride = row_width / 32;
41+
self->stride = row_width / align_bits;
4142
}
4243
self->width = width;
4344
self->height = height;
44-
self->data = m_malloc(self->stride * height * sizeof(uint32_t), false);
45+
self->data = m_malloc(self->stride * height * sizeof(size_t), false);
4546
self->read_only = false;
4647
self->bits_per_value = bits_per_value;
4748

48-
if (bits_per_value > 8) {
49-
mp_raise_NotImplementedError(translate("Only bit maps of 8 bit color or less are supported"));
49+
if (bits_per_value > 8 && bits_per_value != 16 && bits_per_value != 32) {
50+
mp_raise_NotImplementedError(translate("Invalid bits per value"));
5051
}
5152

5253
// Division and modulus can be slow because it has to handle any integer. We know bits_per_value
@@ -56,7 +57,7 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi
5657
self->x_shift = 0; // Used to divide the index by the number of pixels per word. Its used in a
5758
// shift which effectively divides by 2 ** x_shift.
5859
uint32_t power_of_two = 1;
59-
while (power_of_two < 32 / bits_per_value ) {
60+
while (power_of_two < align_bits / bits_per_value ) {
6061
self->x_shift++;
6162
power_of_two <<= 1;
6263
}
@@ -76,57 +77,50 @@ uint32_t common_hal_displayio_bitmap_get_bits_per_value(displayio_bitmap_t *self
7677
return self->bits_per_value;
7778
}
7879

79-
void common_hal_displayio_bitmap_load_row(displayio_bitmap_t *self, uint16_t y, uint8_t* data, uint16_t len) {
80-
if (len != self->stride * sizeof(uint32_t)) {
81-
mp_raise_ValueError(translate("row must be packed and word aligned"));
82-
}
83-
uint32_t* row_value = self->data + (y * self->stride);
84-
// Do the memcpy ourselves since we may want to flip endianness.
85-
for (uint32_t i = 0; i < self->stride; i++) {
86-
#pragma GCC diagnostic push
87-
#pragma GCC diagnostic ignored "-Wcast-align"
88-
uint32_t value = ((uint32_t *)data)[i];
89-
#pragma GCC diagnostic pop
90-
if (self->bits_per_value < 16) {
91-
value = ((value >> 24) & 0xff) |
92-
((value << 8) & 0xff0000) |
93-
((value >> 8) & 0xff00) |
94-
((value << 24) & 0xff000000);
95-
}
96-
*row_value = value;
97-
row_value++;
98-
}
99-
}
100-
10180
uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t x, int16_t y) {
10281
if (x >= self->width || x < 0 || y >= self->height || y < 0) {
10382
return 0;
10483
}
10584
int32_t row_start = y * self->stride;
106-
if (self->bits_per_value < 8) {
107-
uint32_t word = self->data[row_start + (x >> self->x_shift)];
85+
uint32_t bytes_per_value = self->bits_per_value / 8;
86+
if (bytes_per_value < 1) {
87+
size_t word = self->data[row_start + (x >> self->x_shift)];
10888

109-
return (word >> (32 - ((x & self->x_mask) + 1) * self->bits_per_value)) & self->bitmask;
89+
return (word >> (sizeof(size_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value)) & self->bitmask;
11090
} else {
111-
uint32_t bytes_per_value = self->bits_per_value / 8;
112-
return self->data[row_start + x * bytes_per_value];
91+
size_t* row = self->data + row_start;
92+
if (bytes_per_value == 1) {
93+
return ((uint8_t*) row)[x];
94+
} else if (bytes_per_value == 2) {
95+
return ((uint16_t*) row)[x];
96+
} else if (bytes_per_value == 4) {
97+
return ((uint32_t*) row)[x];
98+
}
11399
}
100+
return 0;
114101
}
115102

116103
void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
117104
if (self->read_only) {
118105
mp_raise_RuntimeError(translate("Read-only object"));
119106
}
120107
int32_t row_start = y * self->stride;
121-
if (self->bits_per_value < 8) {
122-
uint32_t bit_position = (32 - ((x & self->x_mask) + 1) * self->bits_per_value);
108+
uint32_t bytes_per_value = self->bits_per_value / 8;
109+
if (bytes_per_value < 1) {
110+
uint32_t bit_position = (sizeof(size_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value);
123111
uint32_t index = row_start + (x >> self->x_shift);
124112
uint32_t word = self->data[index];
125113
word &= ~(self->bitmask << bit_position);
126114
word |= (value & self->bitmask) << bit_position;
127115
self->data[index] = word;
128116
} else {
129-
uint32_t bytes_per_value = self->bits_per_value / 8;
130-
self->data[row_start + x * bytes_per_value] = value;
117+
size_t* row = self->data + row_start;
118+
if (bytes_per_value == 1) {
119+
((uint8_t*) row)[x] = value;
120+
} else if (bytes_per_value == 2) {
121+
((uint16_t*) row)[x] = value;
122+
} else if (bytes_per_value == 4) {
123+
((uint32_t*) row)[x] = value;
124+
}
131125
}
132126
}

shared-module/displayio/Bitmap.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ typedef struct {
3636
mp_obj_base_t base;
3737
uint16_t width;
3838
uint16_t height;
39-
uint32_t* data;
40-
uint16_t stride; // words
39+
size_t* data;
40+
uint16_t stride; // size_t's
4141
uint8_t bits_per_value;
4242
uint8_t x_shift;
43-
uint8_t x_mask;
43+
size_t x_mask;
4444
uint16_t bitmask;
4545
bool read_only;
4646
} displayio_bitmap_t;

supervisor/shared/display.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
#include "shared-bindings/displayio/TileGrid.h"
3535
#include "supervisor/memory.h"
3636

37-
extern uint32_t blinka_bitmap_data[];
37+
extern size_t blinka_bitmap_data[];
3838
extern displayio_bitmap_t blinka_bitmap;
3939
extern displayio_group_t circuitpython_splash;
4040

@@ -107,7 +107,7 @@ void supervisor_display_move_memory(void) {
107107
#endif
108108
}
109109

110-
uint32_t blinka_bitmap_data[32] = {
110+
size_t blinka_bitmap_data[32] = {
111111
0x00000011, 0x11000000,
112112
0x00000111, 0x53100000,
113113
0x00000111, 0x56110000,

tools/gen_display_resources.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ def _load_row(self, y, row):
153153
.base = {{.type = &displayio_bitmap_type }},
154154
.width = {},
155155
.height = {},
156-
.data = (uint32_t*) font_bitmap_data,
156+
.data = (size_t*) font_bitmap_data,
157157
.stride = {},
158158
.bits_per_value = 1,
159159
.x_shift = 5,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy