Skip to content

refactor displayio set_pixel for use in bitmap_tools #4357

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 84 additions & 41 deletions shared-module/displayio/Bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,17 +105,92 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t
return 0;
}

void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, int16_t x1, int16_t y1, int16_t x2, int16_t y2) {
// Update the bitmap's dirty region with the rectangle bounded by (x1,y1) and (x2, y2)

// Arrange x1 < x2, y1 < y2
if (x1 > x2) {
int16_t temp = x1;
x1 = x2;
x2 = temp;
}
if (y1 > y2) {
int16_t temp = y1;
y1 = y2;
y2 = temp;
}

// Update the dirty area.
if (self->dirty_area.x1 == self->dirty_area.x2) {
self->dirty_area.x1 = x1;
self->dirty_area.x2 = x2;
self->dirty_area.y1 = y1;
self->dirty_area.y2 = y2;
} else {
if (x1 < self->dirty_area.x1) {
self->dirty_area.x1 = x1;
}
if (x2 > self->dirty_area.x2) {
self->dirty_area.x2 = x2;
}
if (y1 < self->dirty_area.y1) {
self->dirty_area.y1 = y1;
}
if (y2 > self->dirty_area.y2) {
self->dirty_area.y2 = y2;
}
}
}

void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) {
// Writes the color index value into a pixel position
// Must update the dirty area separately

// Update one pixel of 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 {
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;
}
}
}

void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16_t y, displayio_bitmap_t *source,
int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t skip_index, bool skip_index_none) {
// Copy complete "source" bitmap into "self" bitmap at location x,y in the "self"
// Add a boolean to determine if all values are copied, or only if non-zero
// Copy region of "source" bitmap into "self" bitmap at location x,y in the "self"
// If skip_value is encountered in the source bitmap, it will not be copied.
// If skip_value is `None`, then all pixels are copied.
// This function assumes input checks were performed for pixel index entries.

if (self->read_only) {
mp_raise_RuntimeError(translate("Read-only object"));
}

// Update the dirty area
int16_t dirty_x_max = (x + (x2-x1));
if (dirty_x_max > self->width) {
dirty_x_max = self->width;
}
int16_t dirty_y_max = y + (y2-y1);
if (dirty_y_max > self->height) {
dirty_y_max = self->height;
}

displayio_bitmap_set_dirty_area(self, x, y, dirty_x_max, dirty_y_max);

bool x_reverse = false;
bool y_reverse = false;

Expand All @@ -142,7 +217,7 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16
if ((yd_index >= 0) && (yd_index < self->height) ) {
uint32_t value = common_hal_displayio_bitmap_get_pixel(source, xs_index, ys_index);
if ( (skip_index_none) || (value != skip_index) ) { // write if skip_value_none is True
common_hal_displayio_bitmap_set_pixel(self, xd_index, yd_index, value);
displayio_bitmap_write_pixel(self, xd_index, yd_index, value);
}
}
}
Expand All @@ -154,45 +229,13 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x,
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;
}
}

// 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 {
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;
}
}
// update the dirty region
displayio_bitmap_set_dirty_area(self, x, y, x+1, y+1);

// write the pixel
displayio_bitmap_write_pixel(self, x, y, value);

}

displayio_area_t* displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t* tail) {
Expand Down