diff --git a/subsys/fb/cfb.c b/subsys/fb/cfb.c index 51e381f0e77..80afe824495 100644 --- a/subsys/fb/cfb.c +++ b/subsys/fb/cfb.c @@ -229,6 +229,7 @@ int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y, uint16_t width, uint16_t height) { const struct char_framebuffer *fb = &char_fb; + const bool need_reverse = ((fb->screen_info & SCREEN_INFO_MONO_MSB_FIRST) != 0); if (x >= fb->x_res || y >= fb->y_res) { LOG_ERR("Coordinates outside of framebuffer"); @@ -236,7 +237,15 @@ int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y, return -EINVAL; } - if ((fb->screen_info & SCREEN_INFO_MONO_VTILED) && !(y % 8)) { + if ((fb->screen_info & SCREEN_INFO_MONO_VTILED)) { + if (x > fb->x_res) { + x = fb->x_res; + } + + if (y > fb->y_res) { + y = fb->y_res; + } + if (x + width > fb->x_res) { width = fb->x_res - x; } @@ -246,10 +255,46 @@ int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y, } for (size_t i = x; i < x + width; i++) { - for (size_t j = y / 8U; j < (y + height) / 8U; j++) { - size_t index = (j * fb->x_res) + i; + for (size_t j = y; j < (y + height); j++) { + /* + * Process inversion in the y direction + * by separating per 8-line boundaries. + */ - fb->buf[index] = ~fb->buf[index]; + const size_t index = ((j / 8) * fb->x_res) + i; + const uint8_t remains = y + height - j; + + /* + * Make mask to prevent overwriting the drawing contents that on + * between the start line or end line and the 8-line boundary. + */ + if ((j % 8) > 0) { + uint8_t m = BIT_MASK((j % 8)); + uint8_t b = fb->buf[index]; + + if (need_reverse) { + m = byte_reverse(m); + b = byte_reverse(b); + } + + fb->buf[index] = ~(b | m) | (b & m); + j += 7 - (j % 8); + } else if (remains >= 8) { + /* No mask required if no start or end line is included */ + fb->buf[index] = ~fb->buf[index]; + j += 7; + } else { + uint8_t m = BIT_MASK(remains % 8) << (8 - (remains % 8)); + uint8_t b = fb->buf[index]; + + if (need_reverse) { + m = byte_reverse(m); + b = byte_reverse(b); + } + + fb->buf[index] = ~(b | m) | (b & m); + j += (remains - 1); + } } }