+ max_y = self._height - 1
+ if self._mirror_y:
+ max_y = self._half_height - 1
+ y = clamp(y, 0, max_y)
+ max_x = self._width - 1
+ if self._mirror_x:
+ max_x = self._half_width - 1
+ start_x = clamp(start_x, 0, max_x)
+ end_x = clamp(end_x, 0, max_x)
+
+ # find x-boundaries for updating based on current data and start_x, end_x, and mirror_x
+ lower_x = min(start_x, self._data[2 * y])
+
+ if self._mirror_x:
+ upper_x = (
+ self._width - lower_x + 1
+ ) # dirty rectangles are treated with max value exclusive
+ else:
+ upper_x = max(
+ end_x, self._data[2 * y + 1]
+ ) # dirty rectangles are treated with max value exclusive
+
+ # find y-boundaries based on y and mirror_y
+ lower_y = y
+
+ if self._mirror_y:
+ upper_y = (
+ self._height - lower_y + 1
+ ) # dirty rectangles are treated with max value exclusive
+ else:
+ upper_y = y + 1 # dirty rectangles are treated with max value exclusive
+
+ self._data[2 * y] = start_x # update the data array with the new boundaries
+ self._data[2 * y + 1] = end_x
+
+ if self._dirty_area.x1 == self._dirty_area.x2: # dirty region is empty
+ self._dirty_area.x1 = lower_x
+ self._dirty_area.x2 = upper_x
+ self._dirty_area.y1 = lower_y
+ self._dirty_area.y2 = upper_y
+ else:
+ self._dirty_area.x1 = min(lower_x, self._dirty_area.x1)
+ self._dirty_area.x2 = max(upper_x, self._dirty_area.x2)
+ self._dirty_area.y1 = min(lower_y, self._dirty_area.y1)
+ self._dirty_area.y2 = max(upper_y, self._dirty_area.y2)
+
+ def _get_pixel(self, x: int, y: int) -> int:
+ if x >= self._width or x < 0 or y >= self._height or y < 0:
+ return 0
+ if self._mirror_x and x >= self._half_width:
+ x = self._width - x - 1
+ if self._mirror_y and y >= self._half_height:
+ y = self._height - y - 1
+ start_x = self._data[2 * y]
+ end_x = self._data[2 * y + 1]
+ if x < start_x or x >= end_x:
+ return 0
+ return 1
+
+ def _finish_refresh(self):
+ self._dirty_area.x1 = 0
+ self._dirty_area.x2 = 0
+
+ def _get_refresh_areas(self, areas: list[Area]) -> None:
+ if self._dirty_area.x1 != self._dirty_area.x2:
+ areas.append(self._dirty_area)