From f40c0c13adacf39bc9a21afd2d9ebbf29135e0f0 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 18 Mar 2021 09:04:53 -0500 Subject: displayio: area: add displayo_area_copy_coords, displayio_area_empty .. and simplify the implmentation of displayio_area_union This _slightly_ changes the behavior of displayio_area_union: Formerly, if one of the areas was empty, its coordinates were still used in the min/max calculations. Now, if one of the areas is empty, the result gets the other area's coords In particular, taking the union of the empty area with coords (0,0,0,0) with the non-empty area (x1,y1,x2,y2) would give the area (0,0,x2,y2) before, and (x1,y1,x2,y2) after the change. --- shared-module/displayio/__init__.c | 35 +++++++++++++++++++++-------------- shared-module/displayio/area.h | 2 ++ 2 files changed, 23 insertions(+), 14 deletions(-) (limited to 'shared-module') diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 3c9c2cc3a..07fd60386 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -309,26 +309,33 @@ bool displayio_area_compute_overlap(const displayio_area_t *a, return true; } +void displayio_copy_coords(const displayio_area_t *src, displayio_area_t *dest) { + dest->x1 = src->x1; + dest->y1 = src->y1; + dest->x2 = src->x2; + dest->y2 = src->y2; +} + +bool displayio_area_empty(const displayio_area_t *a) { + return (a->x1 == a->x2) || (a->y1 == a->y2); +} + void displayio_area_union(const displayio_area_t *a, const displayio_area_t *b, displayio_area_t *u) { - u->x1 = a->x1; - if (b->x1 < u->x1) { - u->x1 = b->x1; - } - u->x2 = a->x2; - if (b->x2 > u->x2) { - u->x2 = b->x2; - } - u->y1 = a->y1; - if (b->y1 < u->y1) { - u->y1 = b->y1; + if (displayio_area_empty(a)) { + displayio_copy_coords(b, u); + return; } - u->y2 = a->y2; - if (b->y2 > u->y2) { - u->y2 = b->y2; + if (displayio_area_empty(b)) { + displayio_copy_coords(a, u); + return; } + u->x1 = MIN(a->x1, b->x1); + u->y1 = MIN(a->y1, b->y1); + u->x2 = MAX(a->x2, b->x2); + u->y2 = MAX(a->y2, b->y2); } uint16_t displayio_area_width(const displayio_area_t *area) { diff --git a/shared-module/displayio/area.h b/shared-module/displayio/area.h index 21bf2f8b2..1b30ce96f 100644 --- a/shared-module/displayio/area.h +++ b/shared-module/displayio/area.h @@ -53,6 +53,8 @@ typedef struct { extern displayio_buffer_transform_t null_transform; +bool displayio_area_empty(const displayio_area_t *a); +void displayio_area_copy_coords(const displayio_area_t *src, displayio_area_t *dest); void displayio_area_union(const displayio_area_t *a, const displayio_area_t *b, displayio_area_t *u); -- cgit v1.2.3 From 3b506f0fa59872916b617083a3dad9cadd07c428 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 18 Mar 2021 09:06:00 -0500 Subject: displayio: area: add displayio_area_canon This routine will be used to simplify code that deals with ranges of bitmap coordinates. --- shared-module/displayio/__init__.c | 13 +++++++++++++ shared-module/displayio/area.h | 1 + 2 files changed, 14 insertions(+) (limited to 'shared-module') diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 07fd60386..18d08c530 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -320,6 +320,19 @@ bool displayio_area_empty(const displayio_area_t *a) { return (a->x1 == a->x2) || (a->y1 == a->y2); } +void displayio_area_canon(displayio_area_t *a) { + if (a->x1 < a->x2) { + int16_t t = a->x1; + a->x1 = a->x2; + a->x2 = t; + } + if (a->y1 < a->y2) { + int16_t t = a->y1; + a->y1 = a->y2; + a->y2 = t; + } +} + void displayio_area_union(const displayio_area_t *a, const displayio_area_t *b, displayio_area_t *u) { diff --git a/shared-module/displayio/area.h b/shared-module/displayio/area.h index 1b30ce96f..b6ff1dcd2 100644 --- a/shared-module/displayio/area.h +++ b/shared-module/displayio/area.h @@ -55,6 +55,7 @@ extern displayio_buffer_transform_t null_transform; bool displayio_area_empty(const displayio_area_t *a); void displayio_area_copy_coords(const displayio_area_t *src, displayio_area_t *dest); +void displayio_area_canon(displayio_area_t *a); void displayio_area_union(const displayio_area_t *a, const displayio_area_t *b, displayio_area_t *u); -- cgit v1.2.3 From 36d608aa67229653c0be12fab407533d0d8b7d32 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 18 Mar 2021 09:09:29 -0500 Subject: displayio_bitmap_set_dirty_area: rewrite in terms of displayio_area .. simplifying code in the process. For instance, now fill_region uses area routines to order and constrain its coordinates. Happily, this change also frees a modest amount of code space. --- shared-module/bitmaptools/__init__.c | 42 ++++++++++++-------------------- shared-module/displayio/Bitmap.c | 47 ++++++++---------------------------- shared-module/displayio/Bitmap.h | 2 +- 3 files changed, 26 insertions(+), 65 deletions(-) (limited to 'shared-module') diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 73c8e2f90..604c1a16a 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -240,30 +240,18 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, mp_raise_RuntimeError(translate("Read-only object")); } - // Ensure x1 < x2 and y1 < y2 - if (x1 > x2) { - int16_t temp = x2; - x2 = x1; - x1 = temp; - } - if (y1 > y2) { - int16_t temp = y2; - y2 = y1; - y1 = temp; - } + displayio_area_t area = { x1, y1, x2, y2 }; + displayio_area_canon(&area); - // constrain to bitmap dimensions - x1 = constrain(x1, 0, destination->width); - x2 = constrain(x2, 0, destination->width); - y1 = constrain(y1, 0, destination->height); - y2 = constrain(y2, 0, destination->height); + displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height }; + displayio_area_compute_overlap(&area, &bitmap_area, &area); // update the dirty rectangle - displayio_bitmap_set_dirty_area(destination, x1, y1, x2, y2); + displayio_bitmap_set_dirty_area(destination, &area); int16_t x, y; - for (x = x1; x < x2; x++) { - for (y = y1; y < y2; y++) { + for (x = area.x1; x < area.x2; x++) { + for (y = area.y1; y < area.y2; y++) { displayio_bitmap_write_pixel(destination, x, y, value); } } @@ -298,13 +286,11 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, ybb0 = y1; ybb1 = y0 + 1; } + displayio_area_t area = { xbb0, ybb0, xbb1, ybb1 }; + displayio_area_t bitmap_area = { 0, 0, destination->width, destination->height }; + displayio_area_compute_overlap(&area, &bitmap_area, &area); - xbb0 = constrain(xbb0, 0, destination->width); - xbb1 = constrain(xbb1, 0, destination->width); - ybb0 = constrain(ybb0, 0, destination->height); - ybb1 = constrain(ybb1, 0, destination->height); - - displayio_bitmap_set_dirty_area(destination, xbb0, ybb0, xbb1, ybb1); + displayio_bitmap_set_dirty_area(destination, &area); int16_t temp, x, y; @@ -401,7 +387,8 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int } } } - displayio_bitmap_set_dirty_area(self, x1, y1, x2, y2); + displayio_area_t area = { x1, y1, x2, y2 }; + displayio_bitmap_set_dirty_area(self, &area); } void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_element, bool swap_bytes) { @@ -486,5 +473,6 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *f } } - displayio_bitmap_set_dirty_area(self, 0, 0, self->width, self->height); + displayio_area_t a = {0, 0, self->width, self->height}; + displayio_bitmap_set_dirty_area(self, &a); } diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index f03ade84b..d93338dc4 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -105,41 +105,12 @@ 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_set_dirty_area(displayio_bitmap_t *self, const displayio_area_t *dirty_area) { + displayio_area_t area = *dirty_area; + displayio_area_canon(&area); + displayio_area_union(&area, &self->dirty_area, &area); + displayio_area_t bitmap_area = {0, 0, self->width, self->height}; + displayio_area_compute_overlap(&area, &bitmap_area, &self->dirty_area); } void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value) { @@ -189,7 +160,8 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16 dirty_y_max = self->height; } - displayio_bitmap_set_dirty_area(self, x, y, dirty_x_max, dirty_y_max); + displayio_area_t a = { x, y, dirty_x_max, dirty_y_max}; + displayio_bitmap_set_dirty_area(self, &a); bool x_reverse = false; bool y_reverse = false; @@ -231,7 +203,8 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x, } // update the dirty region - displayio_bitmap_set_dirty_area(self, x, y, x + 1, y + 1); + displayio_area_t a = {x, y, x + 1, y + 1}; + displayio_bitmap_set_dirty_area(self, &a); // write the pixel displayio_bitmap_write_pixel(self, x, y, value); diff --git a/shared-module/displayio/Bitmap.h b/shared-module/displayio/Bitmap.h index c1ce9612b..82a3de631 100644 --- a/shared-module/displayio/Bitmap.h +++ b/shared-module/displayio/Bitmap.h @@ -49,7 +49,7 @@ typedef struct { void displayio_bitmap_finish_refresh(displayio_bitmap_t *self); displayio_area_t *displayio_bitmap_get_refresh_areas(displayio_bitmap_t *self, displayio_area_t *tail); -void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, int16_t x1, int16_t y1, int16_t x2, int16_t y2); +void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, const displayio_area_t *area); void displayio_bitmap_write_pixel(displayio_bitmap_t *self, int16_t x, int16_t y, uint32_t value); #endif // MICROPY_INCLUDED_SHARED_MODULE_DISPLAYIO_BITMAP_H -- cgit v1.2.3 From f5fd42c39340483bc781746fd0acd304abd888ae Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 18 Mar 2021 09:20:21 -0500 Subject: displayio: Move bitmap read-only checking to displayio_bitmap_set_dirty_area This is a modest code savings, but more importantly it reduces boilerplate in bitmap-modifying routines. Callers need only ensure they call displayio_bitmap_set_dirty_area in advance of the bitmap modifications they perform. (note that this assumes that no bitmap operation can enter background tasks. If an operation COULD enter background tasks, it MUST re-dirty the area it touches when it exits, simply by a fresh call to set_dirty_area with the same area as before) --- shared-module/bitmaptools/__init__.c | 23 +++++------------------ shared-module/displayio/Bitmap.c | 22 ++++++---------------- 2 files changed, 11 insertions(+), 34 deletions(-) (limited to 'shared-module') diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 604c1a16a..1c7f36ca2 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -95,10 +95,6 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16 // # */ - if (self->read_only) { - mp_raise_RuntimeError(translate("Read-only object")); - } - int16_t x,y; int16_t minx = dest_clip1_x; @@ -199,6 +195,9 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16 float rowu = startu + miny * duCol; float rowv = startv + miny * dvCol; + displayio_area_t dirty_area = {minx, miny, maxx, maxy}; + displayio_bitmap_set_dirty_area(self, &dirty_area); + for (y = miny; y <= maxy; y++) { float u = rowu + minx * duRow; float v = rowv + minx * dvRow; @@ -236,10 +235,6 @@ void common_hal_bitmaptools_fill_region(displayio_bitmap_t *destination, // // input checks should ensure that x1 < x2 and y1 < y2 and are within the bitmap region - if (destination->read_only) { - mp_raise_RuntimeError(translate("Read-only object")); - } - displayio_area_t area = { x1, y1, x2, y2 }; displayio_area_canon(&area); @@ -262,10 +257,6 @@ void common_hal_bitmaptools_draw_line(displayio_bitmap_t *destination, int16_t x1, int16_t y1, uint32_t value) { - if (destination->read_only) { - mp_raise_RuntimeError(translate("Read-only object")); - } - // // adapted from Adafruit_CircuitPython_Display_Shapes.Polygon._line // @@ -394,9 +385,8 @@ void common_hal_bitmaptools_arrayblit(displayio_bitmap_t *self, void *data, int void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *file, int element_size, int bits_per_pixel, bool reverse_pixels_in_element, bool swap_bytes) { uint32_t mask = (1 << common_hal_displayio_bitmap_get_bits_per_value(self)) - 1; - if (self->read_only) { - mp_raise_RuntimeError(translate("Read-only object")); - } + displayio_area_t a = {0, 0, self->width, self->height}; + displayio_bitmap_set_dirty_area(self, &a); size_t elements_per_row = (self->width * bits_per_pixel + element_size * 8 - 1) / (element_size * 8); size_t rowsize = element_size * elements_per_row; @@ -472,7 +462,4 @@ void common_hal_bitmaptools_readinto(displayio_bitmap_t *self, pyb_file_obj_t *f displayio_bitmap_write_pixel(self, x, y, value & mask); } } - - displayio_area_t a = {0, 0, self->width, self->height}; - displayio_bitmap_set_dirty_area(self, &a); } diff --git a/shared-module/displayio/Bitmap.c b/shared-module/displayio/Bitmap.c index d93338dc4..7b916bb36 100644 --- a/shared-module/displayio/Bitmap.c +++ b/shared-module/displayio/Bitmap.c @@ -106,6 +106,10 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t } void displayio_bitmap_set_dirty_area(displayio_bitmap_t *self, const displayio_area_t *dirty_area) { + if (self->read_only) { + mp_raise_RuntimeError(translate("Read-only object")); + } + displayio_area_t area = *dirty_area; displayio_area_canon(&area); displayio_area_union(&area, &self->dirty_area, &area); @@ -146,10 +150,6 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16 // 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) { @@ -198,10 +198,6 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16 } 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 region displayio_area_t a = {x, y, x + 1, y + 1}; displayio_bitmap_set_dirty_area(self, &a); @@ -225,14 +221,8 @@ void displayio_bitmap_finish_refresh(displayio_bitmap_t *self) { } 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; + displayio_area_t a = {0, 0, self->width, self->height}; + displayio_bitmap_set_dirty_area(self, &a); // build the packed word uint32_t word = 0; -- cgit v1.2.3 From 40829d4cc85394513ca631cff23254344e29786c Mon Sep 17 00:00:00 2001 From: Kevin Matocha Date: Fri, 19 Mar 2021 20:30:37 -0500 Subject: switch to > in displayio_area_canon --- shared-module/displayio/__init__.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'shared-module') diff --git a/shared-module/displayio/__init__.c b/shared-module/displayio/__init__.c index 18d08c530..d238c2816 100644 --- a/shared-module/displayio/__init__.c +++ b/shared-module/displayio/__init__.c @@ -321,12 +321,12 @@ bool displayio_area_empty(const displayio_area_t *a) { } void displayio_area_canon(displayio_area_t *a) { - if (a->x1 < a->x2) { + if (a->x1 > a->x2) { int16_t t = a->x1; a->x1 = a->x2; a->x2 = t; } - if (a->y1 < a->y2) { + if (a->y1 > a->y2) { int16_t t = a->y1; a->y1 = a->y2; a->y2 = t; -- cgit v1.2.3 From 95ac6c716b1f4e9172005b9f8b287d6a4c31836b Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Thu, 18 Mar 2021 09:37:57 -0500 Subject: rotozoom: switch to using set_dirty_area + write_pixel --- shared-module/bitmaptools/__init__.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index 1c7f36ca2..dd3954999 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -205,7 +205,7 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16 if (u >= source_clip0_x && u < source_clip1_x && v >= source_clip0_y && v < source_clip1_y) { uint32_t c = common_hal_displayio_bitmap_get_pixel(source, u, v); if ((skip_index_none) || (c != skip_index)) { - common_hal_displayio_bitmap_set_pixel(self, x, y, c); + displayio_bitmap_write_pixel(self, x, y, c); } } u += duRow; -- cgit v1.2.3 From 9b188934d1c7d11dbfcfb2131692233690d19e93 Mon Sep 17 00:00:00 2001 From: Kevin Matocha Date: Fri, 19 Mar 2021 21:23:55 -0500 Subject: off by one error in rotozoom dirty_area --- shared-module/bitmaptools/__init__.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'shared-module') diff --git a/shared-module/bitmaptools/__init__.c b/shared-module/bitmaptools/__init__.c index dd3954999..2f70e4334 100644 --- a/shared-module/bitmaptools/__init__.c +++ b/shared-module/bitmaptools/__init__.c @@ -195,7 +195,7 @@ void common_hal_bitmaptools_rotozoom(displayio_bitmap_t *self, int16_t ox, int16 float rowu = startu + miny * duCol; float rowv = startv + miny * dvCol; - displayio_area_t dirty_area = {minx, miny, maxx, maxy}; + displayio_area_t dirty_area = {minx, miny, maxx + 1, maxy + 1}; displayio_bitmap_set_dirty_area(self, &dirty_area); for (y = miny; y <= maxy; y++) { -- cgit v1.2.3