summaryrefslogtreecommitdiff
path: root/shared-module/displayio/Bitmap.c
diff options
context:
space:
mode:
authorBenjamin Shockley <benjaminshockley@hotmail.com>2020-08-20 13:48:15 -0500
committerGitHub <noreply@github.com>2020-08-20 13:48:15 -0500
commit0084f0af24e4e219bc040c52ee723959423de6e2 (patch)
tree1aebdb362f08bf6417caa87836e3e4e739afc964 /shared-module/displayio/Bitmap.c
parent9aebe2f1efc99871fcf283c304e3a8700050d736 (diff)
parent4d7b9cde33934a44c4c905a49d2f831339fc8bd2 (diff)
Merge pull request #2 from adafruit/master
Master
Diffstat (limited to 'shared-module/displayio/Bitmap.c')
-rw-r--r--shared-module/displayio/Bitmap.c152
1 files changed, 118 insertions, 34 deletions
diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c
index addc341a7..8bcda6086 100644
--- a/shared-module/displayio/Bitmap.c
+++ b/shared-module/displayio/Bitmap.c
@@ -33,20 +33,21 @@
void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t width,
uint32_t height, uint32_t bits_per_value) {
uint32_t row_width = width * bits_per_value;
- // word align
- if (row_width % 32 != 0) {
- self->stride = (row_width / 32 + 1);
+ // align to size_t
+ uint8_t align_bits = 8 * sizeof(size_t);
+ if (row_width % align_bits != 0) {
+ self->stride = (row_width / align_bits + 1);
} else {
- self->stride = row_width / 32;
+ self->stride = row_width / align_bits;
}
self->width = width;
self->height = height;
- self->data = m_malloc(self->stride * height * sizeof(uint32_t), false);
-
+ self->data = m_malloc(self->stride * height * sizeof(size_t), false);
+ self->read_only = false;
self->bits_per_value = bits_per_value;
- if (bits_per_value > 8) {
- mp_raise_NotImplementedError(translate("Only bit maps of 8 bit color or less are supported"));
+ if (bits_per_value > 8 && bits_per_value != 16 && bits_per_value != 32) {
+ mp_raise_NotImplementedError(translate("Invalid bits per value"));
}
// Division and modulus can be slow because it has to handle any integer. We know bits_per_value
@@ -56,46 +57,129 @@ void common_hal_displayio_bitmap_construct(displayio_bitmap_t *self, uint32_t wi
self->x_shift = 0; // Used to divide the index by the number of pixels per word. Its used in a
// shift which effectively divides by 2 ** x_shift.
uint32_t power_of_two = 1;
- while (power_of_two < 32 / bits_per_value ) {
+ while (power_of_two < align_bits / bits_per_value ) {
self->x_shift++;
power_of_two <<= 1;
}
self->x_mask = (1 << self->x_shift) - 1; // Used as a modulus on the x value
self->bitmask = (1 << bits_per_value) - 1;
+
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = width;
+ self->dirty_area.y1 = 0;
+ self->dirty_area.y2 = height;
}
-void common_hal_displayio_bitmap_load_row(displayio_bitmap_t *self, uint16_t y, uint8_t* data, uint16_t len) {
- if (len != self->stride * sizeof(uint32_t)) {
- mp_raise_ValueError(translate("row must be packed and word aligned"));
- }
- uint32_t* row_value = self->data + (y * self->stride);
- // Do the memcpy ourselves since we may want to flip endianness.
- for (uint32_t i = 0; i < self->stride; i++) {
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wcast-align"
- uint32_t value = ((uint32_t *)data)[i];
- #pragma GCC diagnostic pop
- if (self->bits_per_value < 16) {
- value = ((value >> 24) & 0xff) |
- ((value << 8) & 0xff0000) |
- ((value >> 8) & 0xff00) |
- ((value << 24) & 0xff000000);
- }
- *row_value = value;
- row_value++;
- }
+uint16_t common_hal_displayio_bitmap_get_height(displayio_bitmap_t *self) {
+ return self->height;
+}
+
+uint16_t common_hal_displayio_bitmap_get_width(displayio_bitmap_t *self) {
+ return self->width;
+}
+
+uint32_t common_hal_displayio_bitmap_get_bits_per_value(displayio_bitmap_t *self) {
+ return self->bits_per_value;
}
+
uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t x, int16_t y) {
if (x >= self->width || x < 0 || y >= self->height || y < 0) {
return 0;
}
int32_t row_start = y * self->stride;
- if (self->bits_per_value < 8) {
- uint32_t word = self->data[row_start + (x >> self->x_shift)];
+ uint32_t bytes_per_value = self->bits_per_value / 8;
+ if (bytes_per_value < 1) {
+ size_t word = self->data[row_start + (x >> self->x_shift)];
+
+ return (word >> (sizeof(size_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value)) & self->bitmask;
+ } else {
+ size_t* row = self->data + row_start;
+ if (bytes_per_value == 1) {
+ return ((uint8_t*) row)[x];
+ } else if (bytes_per_value == 2) {
+ return ((uint16_t*) row)[x];
+ } else if (bytes_per_value == 4) {
+ return ((uint32_t*) row)[x];
+ }
+ }
+ return 0;
+}
+
+void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
+ if (self->read_only) {
+ mp_raise_RuntimeError(translate("Read-only object"));
+ }
+ // Update the dirty area.
+ if (self->dirty_area.x1 == self->dirty_area.x2) {
+ self->dirty_area.x1 = x;
+ self->dirty_area.x2 = x + 1;
+ self->dirty_area.y1 = y;
+ self->dirty_area.y2 = y + 1;
+ } else {
+ if (x < self->dirty_area.x1) {
+ self->dirty_area.x1 = x;
+ } else if (x >= self->dirty_area.x2) {
+ self->dirty_area.x2 = x + 1;
+ }
+ if (y < self->dirty_area.y1) {
+ self->dirty_area.y1 = y;
+ } else if (y >= self->dirty_area.y2) {
+ self->dirty_area.y2 = y + 1;
+ }
+ }
- return (word >> (32 - ((x & self->x_mask) + 1) * self->bits_per_value)) & self->bitmask;
+ // Update our data
+ int32_t row_start = y * self->stride;
+ uint32_t bytes_per_value = self->bits_per_value / 8;
+ if (bytes_per_value < 1) {
+ uint32_t bit_position = (sizeof(size_t) * 8 - ((x & self->x_mask) + 1) * self->bits_per_value);
+ uint32_t index = row_start + (x >> self->x_shift);
+ uint32_t word = self->data[index];
+ word &= ~(self->bitmask << bit_position);
+ word |= (value & self->bitmask) << bit_position;
+ self->data[index] = word;
} else {
- uint32_t bytes_per_value = self->bits_per_value / 8;
- return self->data[row_start + x * bytes_per_value];
+ size_t* row = self->data + row_start;
+ if (bytes_per_value == 1) {
+ ((uint8_t*) row)[x] = value;
+ } else if (bytes_per_value == 2) {
+ ((uint16_t*) row)[x] = value;
+ } else if (bytes_per_value == 4) {
+ ((uint32_t*) row)[x] = value;
+ }
+ }
+}
+
+displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail) {
+ if (self->dirty_area.x1 == self->dirty_area.x2) {
+ return tail;
+ }
+ self->dirty_area.next = tail;
+ return &self->dirty_area;
+}
+
+void displayio_bitmap_finish_refresh(displayio_bitmap_t *self) {
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = 0;
+}
+
+void common_hal_displayio_bitmap_fill(displayio_bitmap_t *self, uint32_t value) {
+ if (self->read_only) {
+ mp_raise_RuntimeError(translate("Read-only object"));
+ }
+ // Update the dirty area.
+ self->dirty_area.x1 = 0;
+ self->dirty_area.x2 = self->width;
+ self->dirty_area.y1 = 0;
+ self->dirty_area.y2 = self->height;
+
+ // build the packed word
+ uint32_t word = 0;
+ for (uint8_t i=0; i<32 / self->bits_per_value; i++) {
+ word |= (value & self->bitmask) << (32 - ((i+1)*self->bits_per_value));
+ }
+ // copy it in
+ for (uint32_t i=0; i<self->stride * self->height; i++) {
+ self->data[i] = word;
}
}