From 1c3faabf2472c5eee9ceabc233896e7c28e0d863 Mon Sep 17 00:00:00 2001 From: Yu-Ping Wu Date: Thu, 14 May 2020 10:23:55 +0800 Subject: 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/41392 Tested-by: build bot (Jenkins) Reviewed-by: Julius Werner --- payloads/libpayload/drivers/video/graphics.c | 50 ++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 10 deletions(-) (limited to 'payloads') diff --git a/payloads/libpayload/drivers/video/graphics.c b/payloads/libpayload/drivers/video/graphics.c index ea10f131da..81d2bb9e55 100644 --- a/payloads/libpayload/drivers/video/graphics.c +++ b/payloads/libpayload/drivers/video/graphics.c @@ -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; -- cgit v1.2.3