Skip to content

Commit

Permalink
fb: cfb: Use signed-integer for API that specifies coordinations
Browse files Browse the repository at this point in the history
Change the arguments of `cfb_invert_area`, `cfb_print`, and
`cfb_draw_(point|line|rect)`, which used unsigned integers to specify
coordinates to signed integers.

This is because coordinate calculations are usually based on real
numbers, so it is difficult to use unless negative numbers are
accepted.
We clip drawings outside the drawable area on the implementation side.

Signed-off-by: TOKITA Hiroshi <tokita.hiroshi@gmail.com>
  • Loading branch information
soburi committed Feb 8, 2025
1 parent 95179b2 commit 92922fb
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 28 deletions.
7 changes: 7 additions & 0 deletions doc/releases/migration-guide-4.1.rst
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,13 @@ Networking
Other Subsystems
****************

CFB
===

* Change using signed values to represent the coordinates.
As a result, :c:func:`cfb_print`, :c:func:`cfb_invert_area`,
and :c:struct:`cfb_position` definitions are changed.

Flash map
=========

Expand Down
8 changes: 4 additions & 4 deletions include/zephyr/display/cfb.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ struct cfb_font {
};

struct cfb_position {
uint16_t x;
uint16_t y;
int16_t x;
int16_t y;
};

/**
Expand Down Expand Up @@ -86,7 +86,7 @@ struct cfb_position {
*
* @return 0 on success, negative value otherwise
*/
int cfb_print(const struct device *dev, const char *const str, uint16_t x, uint16_t y);
int cfb_print(const struct device *dev, const char *const str, int16_t x, int16_t y);

/**
* @brief Print a string into the framebuffer.
Expand Down Expand Up @@ -166,7 +166,7 @@ int cfb_framebuffer_invert(const struct device *dev);
*
* @return 0 on success, negative value otherwise
*/
int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y,
int cfb_invert_area(const struct device *dev, int16_t x, int16_t y,
uint16_t width, uint16_t height);

/**
Expand Down
30 changes: 17 additions & 13 deletions subsys/fb/cfb.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ static uint8_t draw_char_vtmono(const struct char_framebuffer *fb,

const int16_t fb_y = y + g_y;
const size_t fb_index = (fb_y / 8U) * fb->x_res + fb_x;
const size_t offset = y % 8;
const size_t offset = (y >= 0) ? y % 8 : (8 + (y % 8));
const uint8_t bottom_lines = ((offset + fptr->height) % 8);
uint8_t bg_mask;
uint8_t byte;
Expand Down Expand Up @@ -331,41 +331,45 @@ int cfb_draw_text(const struct device *dev, const char *const str, int16_t x, in
return draw_text(dev, str, x, y, false);
}

int cfb_print(const struct device *dev, const char *const str, uint16_t x, uint16_t y)
int cfb_print(const struct device *dev, const char *const str, int16_t x, int16_t y)
{
return draw_text(dev, str, x, y, true);
}

int cfb_invert_area(const struct device *dev, uint16_t x, uint16_t y,
int cfb_invert_area(const struct device *dev, int16_t x, int16_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");
if ((x + width) < 0 || x >= fb->x_res) {
return 0;
}

return -EINVAL;
if ((y + height) < 0 || y >= fb->y_res) {
return 0;
}

if ((fb->screen_info & SCREEN_INFO_MONO_VTILED)) {
if (x > fb->x_res) {
x = fb->x_res;
if (x < 0) {
width += x;
x = 0;
}

if (y > fb->y_res) {
y = fb->y_res;
if (y < 0) {
height += y;
y = 0;
}

if (x + width > fb->x_res) {
if (width > (fb->x_res - x)) {
width = fb->x_res - x;
}

if (y + height > fb->y_res) {
if (height > (fb->y_res - y)) {
height = fb->y_res - y;
}

for (size_t i = x; i < x + width; i++) {
for (size_t i = x; i < (x + width); i++) {
for (size_t j = y; j < (y + height); j++) {
/*
* Process inversion in the y direction
Expand Down
31 changes: 20 additions & 11 deletions tests/subsys/display/cfb/basic/src/invert_area.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,26 +66,29 @@ ZTEST(invert_area, test_invert_area_overlapped_2times)

ZTEST(invert_area, test_invert_area_overlap_top_left)
{
int err;
zassert_ok(cfb_invert_area(dev, -10, -10, 20, 20));
zassert_ok(cfb_framebuffer_finalize(dev));

err = cfb_invert_area(dev, -10, -10, 20, 20);
zassert_not_ok(err, "out of rect");
zassert_true(verify_color_inside_rect(0, 0, 10, 10, 0xFFFFFF));
zassert_true(verify_color_outside_rect(0, 0, 10, 10, 0x0));
}

ZTEST(invert_area, test_invert_area_overlap_top_right)
{
int err;
zassert_ok(cfb_invert_area(dev, display_width - 10, -10, 20, 20));
zassert_ok(cfb_framebuffer_finalize(dev));

err = cfb_invert_area(dev, 230, -10, 20, 20);
zassert_not_ok(err, "out of rect");
zassert_true(verify_color_inside_rect(display_width - 10, 0, 10, 10, 0xFFFFFF));
zassert_true(verify_color_outside_rect(display_width - 10, 0, 10, 10, 0x0));
}

ZTEST(invert_area, test_invert_area_overlap_bottom_left)
{
int err;
zassert_ok(cfb_invert_area(dev, -10, display_height - 10, 20, 20));
zassert_ok(cfb_framebuffer_finalize(dev));

err = cfb_invert_area(dev, -10, display_height - 10, 20, 20);
zassert_not_ok(err, "out of rect");
zassert_true(verify_color_inside_rect(0, display_height - 10, 10, 10, 0xFFFFFF));
zassert_true(verify_color_outside_rect(0, display_height - 10, 10, 10, 0x0));
}

ZTEST(invert_area, test_invert_area_overlap_bottom_right)
Expand All @@ -101,12 +104,18 @@ ZTEST(invert_area, test_invert_area_overlap_bottom_right)

ZTEST(invert_area, test_invert_area_outside_top_left)
{
zassert_not_ok(cfb_invert_area(dev, -10, -10, 10, 10), "out of rect");
zassert_ok(cfb_invert_area(dev, -10, -10, 10, 10));
zassert_ok(cfb_framebuffer_finalize(dev));

zassert_true(verify_color_inside_rect(0, 0, display_width, display_height, 0x0));
}

ZTEST(invert_area, test_invert_area_outside_bottom_right)
{
zassert_not_ok(cfb_invert_area(dev, display_width, display_height, 20, 20), "out of rect");
zassert_ok(cfb_invert_area(dev, display_width, display_height, 20, 20));
zassert_ok(cfb_framebuffer_finalize(dev));

zassert_true(verify_color_inside_rect(0, 0, display_width, display_height, 0x0));
}

ZTEST_SUITE(invert_area, NULL, NULL, cfb_test_before, cfb_test_after, NULL);

0 comments on commit 92922fb

Please sign in to comment.