2929#include <string.h>
3030
3131#include "py/runtime.h"
32+ #include "py/misc.h"
3233
3334void common_hal_displayio_shape_construct (displayio_shape_t * self , uint32_t width ,
3435 uint32_t height , bool mirror_x , bool mirror_y ) {
@@ -37,48 +38,88 @@ void common_hal_displayio_shape_construct(displayio_shape_t *self, uint32_t widt
3738 self -> width = width ;
3839 if (self -> mirror_x ) {
3940 width /= 2 ;
40- width += self -> width % 2 - 1 ;
41+ width += self -> width % 2 ;
4142 }
4243 self -> half_width = width ;
4344
4445 self -> height = height ;
4546 if (self -> mirror_y ) {
4647 height /= 2 ;
47- height += self -> height % 2 - 1 ;
48+ height += self -> height % 2 ;
4849 }
4950 self -> half_height = height ;
5051
5152 self -> data = m_malloc (height * sizeof (uint32_t ), false);
52- for (uint16_t i = 0 ; i <= height ; i ++ ) {
53+
54+ for (uint16_t i = 0 ; i < height ; i ++ ) {
5355 self -> data [2 * i ] = 0 ;
5456 self -> data [2 * i + 1 ] = width ;
5557 }
58+
59+ self -> dirty_area .x1 = 0 ;
60+ self -> dirty_area .x2 = width ;
61+ self -> dirty_area .y1 = 0 ;
62+ self -> dirty_area .y2 = height ;
5663}
5764
5865void common_hal_displayio_shape_set_boundary (displayio_shape_t * self , uint16_t y , uint16_t start_x , uint16_t end_x ) {
59- if (y < 0 || y >= self -> height || (self -> mirror_y && y > self -> half_height )) {
66+ if (y < 0 || y >= self -> height || (self -> mirror_y && y >= self -> half_height )) {
6067 mp_raise_ValueError (translate ("y value out of bounds" ));
6168 }
62- if (start_x < 0 || start_x > self -> width || end_x < 0 || end_x > self -> width ) {
69+ if (start_x < 0 || start_x >= self -> width || end_x < 0 || end_x >= self -> width ) {
6370 mp_raise_ValueError (translate ("x value out of bounds" ));
6471 }
65- uint16_t half_width = self -> width / 2 - 1 + self -> width % 2 ;
66- if (self -> mirror_x && (start_x > half_width || end_x > half_width )) {
67- mp_raise_ValueError_varg (translate ("Maximum x value when mirrored is %d" ), half_width );
72+ if (self -> mirror_x && (start_x >= self -> half_width || end_x >= self -> half_width )) {
73+ mp_raise_ValueError_varg (translate ("Maximum x value when mirrored is %d" ), self -> half_width );
74+ }
75+
76+ uint16_t lower_x , upper_x , lower_y , upper_y ;
77+
78+ // find x-boundaries for updating based on current data and start_x, end_x, and mirror_x
79+ lower_x = MIN (start_x , self -> data [2 * y ]);
80+
81+ if (self -> mirror_x ) {
82+ upper_x = self -> width - lower_x + 1 ; // dirty rectangles are treated with max value exclusive
83+ } else {
84+ upper_x = MAX (end_x , self -> data [2 * y + 1 ]) + 1 ; // dirty rectangles are treated with max value exclusive
85+ }
86+
87+ // find y-boundaries based on y and mirror_y
88+ lower_y = y ;
89+
90+ if (self -> mirror_y ) {
91+ upper_y = self -> height - lower_y + 1 ; // dirty rectangles are treated with max value exclusive
92+ } else {
93+ upper_y = y + 1 ; // dirty rectangles are treated with max value exclusive
6894 }
69- self -> data [2 * y ] = start_x ;
95+
96+ self -> data [2 * y ] = start_x ; // update the data array with the new boundaries
7097 self -> data [2 * y + 1 ] = end_x ;
98+
99+ if (self -> dirty_area .x1 == self -> dirty_area .x2 ) { // Dirty region is empty
100+ self -> dirty_area .x1 = lower_x ;
101+ self -> dirty_area .x2 = upper_x ;
102+ self -> dirty_area .y1 = lower_y ;
103+ self -> dirty_area .y2 = upper_y ;
104+
105+ } else { // Dirty region is not empty
106+ self -> dirty_area .x1 = MIN (lower_x , self -> dirty_area .x1 );
107+ self -> dirty_area .x2 = MAX (upper_x , self -> dirty_area .x2 );
108+
109+ self -> dirty_area .y1 = MIN (lower_y , self -> dirty_area .y1 );
110+ self -> dirty_area .y2 = MAX (upper_y , self -> dirty_area .y2 );
111+ }
71112}
72113
73114uint32_t common_hal_displayio_shape_get_pixel (void * obj , int16_t x , int16_t y ) {
74115 displayio_shape_t * self = obj ;
75116 if (x >= self -> width || x < 0 || y >= self -> height || y < 0 ) {
76117 return 0 ;
77118 }
78- if (self -> mirror_x && x > self -> half_width ) {
79- x = self -> width - 1 - x ;
119+ if (self -> mirror_x && x >= self -> half_width ) {
120+ x = self -> width - x - 1 ;
80121 }
81- if (self -> mirror_y && y > self -> half_height ) {
122+ if (self -> mirror_y && y >= self -> half_height ) {
82123 y = self -> height - y - 1 ;
83124 }
84125 uint16_t start_x = self -> data [2 * y ];
@@ -88,3 +129,16 @@ uint32_t common_hal_displayio_shape_get_pixel(void *obj, int16_t x, int16_t y) {
88129 }
89130 return 1 ;
90131}
132+
133+ displayio_area_t * displayio_shape_get_refresh_areas (displayio_shape_t * self , displayio_area_t * tail ) {
134+ if (self -> dirty_area .x1 == self -> dirty_area .x2 ) {
135+ return tail ;
136+ }
137+ self -> dirty_area .next = tail ;
138+ return & self -> dirty_area ;
139+ }
140+
141+ void displayio_shape_finish_refresh (displayio_shape_t * self ) {
142+ self -> dirty_area .x1 = 0 ;
143+ self -> dirty_area .x2 = 0 ;
144+ }
0 commit comments