[PATCH v2 1/1] video: fix positioning in TrueType console

Heinrich Schuchardt xypron.glpk at gmx.de
Thu Oct 28 09:07:01 CEST 2021


On 10/28/21 7:19 AM, Heinrich Schuchardt wrote:
> With the patch accurate positioning is possible for mono-typed fonts:
>
> Fix the return value of console_truetype_putc_xy(). The current position
> is passed as parameter x. Some part of x represents a fractional pixel.
> The return value represents how much the character position must be
> advanced. This should only comprise the width of the current character and
> not the preexisting fractional pixel position.
>
> Characters are not square. As all characters of a mono-type font we can
> take the width of any character. 'W' as one of the widest ANSI characters
> provides also a good value for variable width fonts.
>
> The character width must be a float.
>
> Signed-off-by: Heinrich Schuchardt <xypron.glpk at gmx.de>
> ---
> v2:
> 	Adjust hash values in tests

There is still something wrong for systems without float support:

undefined reference to `__aeabi_dmul'

We should keep usage of floats restricted to truetype.

Best regards

Heinrich

> ---
>   drivers/video/console_truetype.c | 27 ++++++++++++++++++++-------
>   include/video_console.h          |  2 +-
>   test/dm/video.c                  |  6 +++---
>   3 files changed, 24 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c
> index d9ad52cce0..6fe238eab3 100644
> --- a/drivers/video/console_truetype.c
> +++ b/drivers/video/console_truetype.c
> @@ -209,7 +209,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
>   	int width_frac, linenum;
>   	struct pos_info *pos;
>   	u8 *bits, *data;
> -	int advance;
> +	int advance, kern_adv;
>   	void *start, *line, *sync_start, *sync_end;
>   	int row, ret;
>   	int bg_r, bg_g, bg_b;
> @@ -224,8 +224,11 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
>   	 * this character */
>   	xpos = frac(VID_TO_PIXEL((double)x));
>   	if (vc_priv->last_ch) {
> -		xpos += priv->scale * stbtt_GetCodepointKernAdvance(font,
> -							vc_priv->last_ch, ch);
> +		kern_adv = stbtt_GetCodepointKernAdvance(font, vc_priv->last_ch,
> +							 ch);
> +		xpos += priv->scale * kern_adv;
> +	} else {
> +		kern_adv = 0;
>   	}
>
>   	/*
> @@ -236,8 +239,8 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
>   	 */
>   	x_shift = xpos - (double)tt_floor(xpos);
>   	xpos += advance * priv->scale;
> -	width_frac = (int)VID_TO_POS(xpos);
> -	if (x + width_frac >= vc_priv->xsize_frac)
> +	width_frac = VID_TO_POS(priv->scale * (kern_adv + advance));
> +	if (x + (int)VID_TO_POS(xpos) >= vc_priv->xsize_frac)
>   		return -EAGAIN;
>
>   	/* Write the current cursor position into history */
> @@ -585,20 +588,21 @@ static int console_truetype_probe(struct udevice *dev)
>   	struct udevice *vid_dev = dev->parent;
>   	struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
>   	stbtt_fontinfo *font = &priv->font;
> -	int ascent;
> +	int advance, ascent, lsb;
>
>   	debug("%s: start\n", __func__);
> +
>   	if (vid_priv->font_size)
>   		priv->font_size = vid_priv->font_size;
>   	else
>   		priv->font_size = CONFIG_CONSOLE_TRUETYPE_SIZE;
> +
>   	priv->font_data = console_truetype_find_font();
>   	if (!priv->font_data) {
>   		debug("%s: Could not find any fonts\n", __func__);
>   		return -EBFONT;
>   	}
>
> -	vc_priv->x_charsize = priv->font_size;
>   	vc_priv->y_charsize = priv->font_size;
>   	vc_priv->xstart_frac = VID_TO_POS(2);
>   	vc_priv->cols = vid_priv->xsize / priv->font_size;
> @@ -612,6 +616,15 @@ static int console_truetype_probe(struct udevice *dev)
>
>   	/* Pre-calculate some things we will need regularly */
>   	priv->scale = stbtt_ScaleForPixelHeight(font, priv->font_size);
> +
> +	/* Assuming that 'W' is the widest character */
> +	stbtt_GetCodepointHMetrics(font, 'W', &advance, &lsb);
> +	advance += stbtt_GetCodepointKernAdvance(font, 'W', 'W');
> +	vc_priv->cols =
> +		(int)VID_TO_POS(vid_priv->xsize - 2) /
> +		(int)VID_TO_POS(advance * priv->scale);
> +	vc_priv->x_charsize = advance * priv->scale;
> +
>   	stbtt_GetFontVMetrics(font, &ascent, 0, 0);
>   	priv->baseline = (int)(ascent * priv->scale);
>   	debug("%s: ready\n", __func__);
> diff --git a/include/video_console.h b/include/video_console.h
> index 06b798ef10..6ec9b4c5b0 100644
> --- a/include/video_console.h
> +++ b/include/video_console.h
> @@ -68,7 +68,7 @@ struct vidconsole_priv {
>   	int ycur;
>   	int rows;
>   	int cols;
> -	int x_charsize;
> +	double x_charsize;
>   	int y_charsize;
>   	int tab_width_frac;
>   	int xsize_frac;
> diff --git a/test/dm/video.c b/test/dm/video.c
> index 1d29b2d61c..c0ad83521a 100644
> --- a/test/dm/video.c
> +++ b/test/dm/video.c
> @@ -344,7 +344,7 @@ static int dm_test_video_truetype(struct unit_test_state *uts)
>   	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
>   	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
>   	vidconsole_put_string(con, test_string);
> -	ut_asserteq(13001, compress_frame_buffer(uts, dev));
> +	ut_asserteq(12752, compress_frame_buffer(uts, dev));
>
>   	return 0;
>   }
> @@ -365,7 +365,7 @@ static int dm_test_video_truetype_scroll(struct unit_test_state *uts)
>   	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
>   	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
>   	vidconsole_put_string(con, test_string);
> -	ut_asserteq(36952, compress_frame_buffer(uts, dev));
> +	ut_asserteq(36493, compress_frame_buffer(uts, dev));
>
>   	return 0;
>   }
> @@ -386,7 +386,7 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts)
>   	ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev));
>   	ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con));
>   	vidconsole_put_string(con, test_string);
> -	ut_asserteq(30747, compress_frame_buffer(uts, dev));
> +	ut_asserteq(31117, compress_frame_buffer(uts, dev));
>
>   	return 0;
>   }
> --
> 2.30.2
>



More information about the U-Boot mailing list