libpayload/cbgfx: Remove gap between adjacent boxes

When drawing two adjacent boxes with draw_box(), there will be a gap
between them. This is due to the truncation in integer division when
calculating the bottom right coordinate of the box.

In this patch, the relative bottom right coordinate is calculated before
transforming to an absolute one. The same issue is also fixed for
draw_rounded_box().

Also check validity of 'pos_rel' and 'dim_rel' arguments for
draw_rounded_box().

BRANCH=none
BUG=chromium:1082593
TEST=emerge-nami libpayload

Change-Id: I073cf8ec6eb3952a0dcb417b4c3c3c7047567837
Signed-off-by: Yu-Ping Wu <yupingso@chromium.org>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/41392
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Julius Werner <jwerner@chromium.org>
This commit is contained in:
Yu-Ping Wu 2020-05-14 10:23:55 +08:00 committed by Patrick Georgi
parent 309ccf74dd
commit 1c3faabf24
1 changed files with 40 additions and 10 deletions

View File

@ -72,6 +72,35 @@ static int is_valid_fraction(const struct fraction *f)
return f->d != 0;
}
static int is_valid_scale(const struct scale *s)
{
return is_valid_fraction(&s->x) && is_valid_fraction(&s->y);
}
static void add_fractions(struct fraction *out,
const struct fraction *f1, const struct fraction *f2)
{
int64_t n, d;
int shift;
n = (int64_t)f1->n * f2->d + (int64_t)f2->n * f1->d;
d = (int64_t)f1->d * f2->d;
/* Simplest way to reduce the fraction until fitting in int32_t */
shift = log2(MAX(ABS(n), ABS(d)) >> 31);
if (shift > 0) {
n >>= shift;
d >>= shift;
}
out->n = n;
out->d = d;
}
static void add_scales(struct scale *out,
const struct scale *s1, const struct scale *s2)
{
add_fractions(&out->x, &s1->x, &s2->x);
add_fractions(&out->y, &s1->y, &s2->y);
}
/*
* Transform a vector:
* x' = x * a_x + offset_x
@ -82,7 +111,7 @@ static int transform_vector(struct vector *out,
const struct scale *a,
const struct vector *offset)
{
if (!is_valid_fraction(&a->x) || !is_valid_fraction(&a->y))
if (!is_valid_scale(a))
return CBGFX_ERROR_INVALID_PARAMETER;
out->x = a->x.n * in->x / a->x.d + offset->x;
out->y = a->y.n * in->y / a->y.d + offset->y;
@ -211,7 +240,6 @@ static int cbgfx_init(void)
int draw_box(const struct rect *box, const struct rgb_color *rgb)
{
struct vector top_left;
struct vector size;
struct vector p, t;
if (cbgfx_init())
@ -222,14 +250,13 @@ int draw_box(const struct rect *box, const struct rgb_color *rgb)
.x = { .n = box->offset.x, .d = CANVAS_SCALE, },
.y = { .n = box->offset.y, .d = CANVAS_SCALE, }
};
const struct scale size_s = {
.x = { .n = box->size.x, .d = CANVAS_SCALE, },
.y = { .n = box->size.y, .d = CANVAS_SCALE, }
const struct scale bottom_right_s = {
.x = { .n = box->offset.x + box->size.x, .d = CANVAS_SCALE, },
.y = { .n = box->offset.y + box->size.y, .d = CANVAS_SCALE, }
};
transform_vector(&top_left, &canvas.size, &top_left_s, &canvas.offset);
transform_vector(&size, &canvas.size, &size_s, &vzero);
add_vectors(&t, &top_left, &size);
transform_vector(&t, &canvas.size, &bottom_right_s, &canvas.offset);
if (within_box(&t, &canvas) < 0) {
LOG("Box exceeds canvas boundary\n");
return CBGFX_ERROR_BOUNDARY;
@ -247,8 +274,8 @@ int draw_rounded_box(const struct scale *pos_rel, const struct scale *dim_rel,
const struct fraction *thickness,
const struct fraction *radius)
{
struct scale pos_end_rel;
struct vector top_left;
struct vector size;
struct vector p, t;
if (cbgfx_init())
@ -256,9 +283,12 @@ int draw_rounded_box(const struct scale *pos_rel, const struct scale *dim_rel,
const uint32_t color = calculate_color(rgb, 0);
if (!is_valid_scale(pos_rel) || !is_valid_scale(dim_rel))
return CBGFX_ERROR_INVALID_PARAMETER;
add_scales(&pos_end_rel, pos_rel, dim_rel);
transform_vector(&top_left, &canvas.size, pos_rel, &canvas.offset);
transform_vector(&size, &canvas.size, dim_rel, &vzero);
add_vectors(&t, &top_left, &size);
transform_vector(&t, &canvas.size, &pos_end_rel, &canvas.offset);
if (within_box(&t, &canvas) < 0) {
LOG("Box exceeds canvas boundary\n");
return CBGFX_ERROR_BOUNDARY;