From 70685875059fee1e63517cbb892dae36b3bb9e67 Mon Sep 17 00:00:00 2001 From: TOKITA Hiroshi Date: Thu, 12 Jan 2023 22:26:34 +0900 Subject: [PATCH] fb: cfb: support inverting with coordinates that do not align with the tile Improve `cfb_invert_area()` able to invert even at a coordinate not on tile boundaries. Signed-off-by: TOKITA Hiroshi --- subsys/fb/cfb.c | 53 +++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) 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); + } } }