@@ -105,17 +105,92 @@ uint32_t common_hal_displayio_bitmap_get_pixel(displayio_bitmap_t *self, int16_t
105105 return 0 ;
106106}
107107
108+ void displayio_bitmap_set_dirty_area (displayio_bitmap_t * self , int16_t x1 , int16_t y1 , int16_t x2 , int16_t y2 ) {
109+ // Update the bitmap's dirty region with the rectangle bounded by (x1,y1) and (x2, y2)
110+
111+ // Arrange x1 < x2, y1 < y2
112+ if (x1 > x2 ) {
113+ int16_t temp = x1 ;
114+ x1 = x2 ;
115+ x2 = temp ;
116+ }
117+ if (y1 > y2 ) {
118+ int16_t temp = y1 ;
119+ y1 = y2 ;
120+ y2 = temp ;
121+ }
122+
123+ // Update the dirty area.
124+ if (self -> dirty_area .x1 == self -> dirty_area .x2 ) {
125+ self -> dirty_area .x1 = x1 ;
126+ self -> dirty_area .x2 = x2 ;
127+ self -> dirty_area .y1 = y1 ;
128+ self -> dirty_area .y2 = y2 ;
129+ } else {
130+ if (x1 < self -> dirty_area .x1 ) {
131+ self -> dirty_area .x1 = x1 ;
132+ }
133+ if (x2 > self -> dirty_area .x2 ) {
134+ self -> dirty_area .x2 = x2 ;
135+ }
136+ if (y1 < self -> dirty_area .y1 ) {
137+ self -> dirty_area .y1 = y1 ;
138+ }
139+ if (y2 > self -> dirty_area .y2 ) {
140+ self -> dirty_area .y2 = y2 ;
141+ }
142+ }
143+ }
144+
145+ void displayio_bitmap_write_pixel (displayio_bitmap_t * self , int16_t x , int16_t y , uint32_t value ) {
146+ // Writes the color index value into a pixel position
147+ // Must update the dirty area separately
148+
149+ // Update one pixel of data
150+ int32_t row_start = y * self -> stride ;
151+ uint32_t bytes_per_value = self -> bits_per_value / 8 ;
152+ if (bytes_per_value < 1 ) {
153+ uint32_t bit_position = (sizeof (size_t ) * 8 - ((x & self -> x_mask ) + 1 ) * self -> bits_per_value );
154+ uint32_t index = row_start + (x >> self -> x_shift );
155+ uint32_t word = self -> data [index ];
156+ word &= ~(self -> bitmask << bit_position );
157+ word |= (value & self -> bitmask ) << bit_position ;
158+ self -> data [index ] = word ;
159+ } else {
160+ size_t * row = self -> data + row_start ;
161+ if (bytes_per_value == 1 ) {
162+ ((uint8_t * ) row )[x ] = value ;
163+ } else if (bytes_per_value == 2 ) {
164+ ((uint16_t * ) row )[x ] = value ;
165+ } else if (bytes_per_value == 4 ) {
166+ ((uint32_t * ) row )[x ] = value ;
167+ }
168+ }
169+ }
170+
108171void common_hal_displayio_bitmap_blit (displayio_bitmap_t * self , int16_t x , int16_t y , displayio_bitmap_t * source ,
109172 int16_t x1 , int16_t y1 , int16_t x2 , int16_t y2 , uint32_t skip_index , bool skip_index_none ) {
110- // Copy complete "source" bitmap into "self" bitmap at location x,y in the "self"
111- // Add a boolean to determine if all values are copied, or only if non-zero
173+ // Copy region of "source" bitmap into "self" bitmap at location x,y in the "self"
112174 // If skip_value is encountered in the source bitmap, it will not be copied.
113175 // If skip_value is `None`, then all pixels are copied.
176+ // This function assumes input checks were performed for pixel index entries.
114177
115178 if (self -> read_only ) {
116179 mp_raise_RuntimeError (translate ("Read-only object" ));
117180 }
118181
182+ // Update the dirty area
183+ int16_t dirty_x_max = (x + (x2 - x1 ));
184+ if (dirty_x_max > self -> width ) {
185+ dirty_x_max = self -> width ;
186+ }
187+ int16_t dirty_y_max = y + (y2 - y1 );
188+ if (dirty_y_max > self -> height ) {
189+ dirty_y_max = self -> height ;
190+ }
191+
192+ displayio_bitmap_set_dirty_area (self , x , y , dirty_x_max , dirty_y_max );
193+
119194 bool x_reverse = false;
120195 bool y_reverse = false;
121196
@@ -142,7 +217,7 @@ void common_hal_displayio_bitmap_blit(displayio_bitmap_t *self, int16_t x, int16
142217 if ((yd_index >= 0 ) && (yd_index < self -> height ) ) {
143218 uint32_t value = common_hal_displayio_bitmap_get_pixel (source , xs_index , ys_index );
144219 if ( (skip_index_none ) || (value != skip_index ) ) { // write if skip_value_none is True
145- common_hal_displayio_bitmap_set_pixel (self , xd_index , yd_index , value );
220+ displayio_bitmap_write_pixel (self , xd_index , yd_index , value );
146221 }
147222 }
148223 }
@@ -154,45 +229,13 @@ void common_hal_displayio_bitmap_set_pixel(displayio_bitmap_t *self, int16_t x,
154229 if (self -> read_only ) {
155230 mp_raise_RuntimeError (translate ("Read-only object" ));
156231 }
157- // Update the dirty area.
158- if (self -> dirty_area .x1 == self -> dirty_area .x2 ) {
159- self -> dirty_area .x1 = x ;
160- self -> dirty_area .x2 = x + 1 ;
161- self -> dirty_area .y1 = y ;
162- self -> dirty_area .y2 = y + 1 ;
163- } else {
164- if (x < self -> dirty_area .x1 ) {
165- self -> dirty_area .x1 = x ;
166- } else if (x >= self -> dirty_area .x2 ) {
167- self -> dirty_area .x2 = x + 1 ;
168- }
169- if (y < self -> dirty_area .y1 ) {
170- self -> dirty_area .y1 = y ;
171- } else if (y >= self -> dirty_area .y2 ) {
172- self -> dirty_area .y2 = y + 1 ;
173- }
174- }
175232
176- // Update our data
177- int32_t row_start = y * self -> stride ;
178- uint32_t bytes_per_value = self -> bits_per_value / 8 ;
179- if (bytes_per_value < 1 ) {
180- uint32_t bit_position = (sizeof (size_t ) * 8 - ((x & self -> x_mask ) + 1 ) * self -> bits_per_value );
181- uint32_t index = row_start + (x >> self -> x_shift );
182- uint32_t word = self -> data [index ];
183- word &= ~(self -> bitmask << bit_position );
184- word |= (value & self -> bitmask ) << bit_position ;
185- self -> data [index ] = word ;
186- } else {
187- size_t * row = self -> data + row_start ;
188- if (bytes_per_value == 1 ) {
189- ((uint8_t * ) row )[x ] = value ;
190- } else if (bytes_per_value == 2 ) {
191- ((uint16_t * ) row )[x ] = value ;
192- } else if (bytes_per_value == 4 ) {
193- ((uint32_t * ) row )[x ] = value ;
194- }
195- }
233+ // update the dirty region
234+ displayio_bitmap_set_dirty_area (self , x , y , x + 1 , y + 1 );
235+
236+ // write the pixel
237+ displayio_bitmap_write_pixel (self , x , y , value );
238+
196239}
197240
198241displayio_area_t * displayio_bitmap_get_refresh_areas (displayio_bitmap_t * self , displayio_area_t * tail ) {
0 commit comments