mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
video: Refactor to allow more than one font size
At present the truetype console supports only a single font and size. It is useful to be able to support different combinations. As a first step, move the metrics into there own structure and allow having multiple metrics. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
5330612f21
commit
31efa25095
2 changed files with 113 additions and 42 deletions
|
@ -176,6 +176,21 @@ config CONSOLE_TRUETYPE_SIZE
|
||||||
method to select the display's physical size, which would allow
|
method to select the display's physical size, which would allow
|
||||||
U-Boot to calculate the correct font size.
|
U-Boot to calculate the correct font size.
|
||||||
|
|
||||||
|
config CONSOLE_TRUETYPE_MAX_METRICS
|
||||||
|
int "TrueType maximum number of font / size combinations"
|
||||||
|
depends on CONSOLE_TRUETYPE
|
||||||
|
default 10 if EXPO
|
||||||
|
default 1
|
||||||
|
help
|
||||||
|
This sets the number of font / size combinations which can be used by
|
||||||
|
the console. For simple console use a single font is enough. When
|
||||||
|
boot menus are in use, this may need to be increased.
|
||||||
|
|
||||||
|
Note that a separate entry is needed for each font size, even if the
|
||||||
|
font itself is the same. This is because the entry caches various
|
||||||
|
font metrics which are expensive to regenerate each time the font
|
||||||
|
size changes.
|
||||||
|
|
||||||
config SYS_WHITE_ON_BLACK
|
config SYS_WHITE_ON_BLACK
|
||||||
bool "Display console as white on a black background"
|
bool "Display console as white on a black background"
|
||||||
default y if ARCH_AT91 || ARCH_EXYNOS || ARCH_ROCKCHIP || ARCH_TEGRA || X86 || ARCH_SUNXI
|
default y if ARCH_AT91 || ARCH_EXYNOS || ARCH_ROCKCHIP || ARCH_TEGRA || X86 || ARCH_SUNXI
|
||||||
|
|
|
@ -94,17 +94,15 @@ struct pos_info {
|
||||||
#define POS_HISTORY_SIZE (CONFIG_SYS_CBSIZE * 11 / 10)
|
#define POS_HISTORY_SIZE (CONFIG_SYS_CBSIZE * 11 / 10)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct console_tt_priv - Private data for this driver
|
* struct console_tt_metrics - Information about a font / size combination
|
||||||
|
*
|
||||||
|
* This caches various font metrics which are expensive to regenerate each time
|
||||||
|
* the font size changes. There is one of these for each font / size combination
|
||||||
|
* that is being used
|
||||||
*
|
*
|
||||||
* @font_size: Vertical font size in pixels
|
* @font_size: Vertical font size in pixels
|
||||||
* @font_data: Pointer to TrueType font file contents
|
* @font_data: Pointer to TrueType font file contents
|
||||||
* @font: TrueType font information for the current font
|
* @font: TrueType font information for the current font
|
||||||
* @pos: List of cursor positions for each character written. This is
|
|
||||||
* used to handle backspace. We clear the frame buffer between
|
|
||||||
* the last position and the current position, thus erasing the
|
|
||||||
* last character. We record enough characters to go back to the
|
|
||||||
* start of the current command line.
|
|
||||||
* @pos_ptr: Current position in the position history
|
|
||||||
* @baseline: Pixel offset of the font's baseline from the cursor position.
|
* @baseline: Pixel offset of the font's baseline from the cursor position.
|
||||||
* This is the 'ascent' of the font, scaled to pixel coordinates.
|
* This is the 'ascent' of the font, scaled to pixel coordinates.
|
||||||
* It measures the distance from the baseline to the top of the
|
* It measures the distance from the baseline to the top of the
|
||||||
|
@ -113,25 +111,45 @@ struct pos_info {
|
||||||
* of the font. It is used by the STB library to generate images
|
* of the font. It is used by the STB library to generate images
|
||||||
* of the correct size.
|
* of the correct size.
|
||||||
*/
|
*/
|
||||||
struct console_tt_priv {
|
struct console_tt_metrics {
|
||||||
int font_size;
|
int font_size;
|
||||||
u8 *font_data;
|
const u8 *font_data;
|
||||||
stbtt_fontinfo font;
|
stbtt_fontinfo font;
|
||||||
struct pos_info pos[POS_HISTORY_SIZE];
|
|
||||||
int pos_ptr;
|
|
||||||
int baseline;
|
int baseline;
|
||||||
double scale;
|
double scale;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct console_tt_priv - Private data for this driver
|
||||||
|
*
|
||||||
|
* @cur_met: Current metrics being used
|
||||||
|
* @metrics: List metrics that can be used
|
||||||
|
* @num_metrics: Number of available metrics
|
||||||
|
* @pos: List of cursor positions for each character written. This is
|
||||||
|
* used to handle backspace. We clear the frame buffer between
|
||||||
|
* the last position and the current position, thus erasing the
|
||||||
|
* last character. We record enough characters to go back to the
|
||||||
|
* start of the current command line.
|
||||||
|
* @pos_ptr: Current position in the position history
|
||||||
|
*/
|
||||||
|
struct console_tt_priv {
|
||||||
|
struct console_tt_metrics *cur_met;
|
||||||
|
struct console_tt_metrics metrics[CONFIG_CONSOLE_TRUETYPE_MAX_METRICS];
|
||||||
|
int num_metrics;
|
||||||
|
struct pos_info pos[POS_HISTORY_SIZE];
|
||||||
|
int pos_ptr;
|
||||||
|
};
|
||||||
|
|
||||||
static int console_truetype_set_row(struct udevice *dev, uint row, int clr)
|
static int console_truetype_set_row(struct udevice *dev, uint row, int clr)
|
||||||
{
|
{
|
||||||
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
|
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
|
||||||
struct console_tt_priv *priv = dev_get_priv(dev);
|
struct console_tt_priv *priv = dev_get_priv(dev);
|
||||||
|
struct console_tt_metrics *met = priv->cur_met;
|
||||||
void *end, *line;
|
void *end, *line;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
line = vid_priv->fb + row * priv->font_size * vid_priv->line_length;
|
line = vid_priv->fb + row * met->font_size * vid_priv->line_length;
|
||||||
end = line + priv->font_size * vid_priv->line_length;
|
end = line + met->font_size * vid_priv->line_length;
|
||||||
|
|
||||||
switch (vid_priv->bpix) {
|
switch (vid_priv->bpix) {
|
||||||
#ifdef CONFIG_VIDEO_BPP8
|
#ifdef CONFIG_VIDEO_BPP8
|
||||||
|
@ -176,19 +194,20 @@ static int console_truetype_move_rows(struct udevice *dev, uint rowdst,
|
||||||
{
|
{
|
||||||
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
|
struct video_priv *vid_priv = dev_get_uclass_priv(dev->parent);
|
||||||
struct console_tt_priv *priv = dev_get_priv(dev);
|
struct console_tt_priv *priv = dev_get_priv(dev);
|
||||||
|
struct console_tt_metrics *met = priv->cur_met;
|
||||||
void *dst;
|
void *dst;
|
||||||
void *src;
|
void *src;
|
||||||
int i, diff, ret;
|
int i, diff, ret;
|
||||||
|
|
||||||
dst = vid_priv->fb + rowdst * priv->font_size * vid_priv->line_length;
|
dst = vid_priv->fb + rowdst * met->font_size * vid_priv->line_length;
|
||||||
src = vid_priv->fb + rowsrc * priv->font_size * vid_priv->line_length;
|
src = vid_priv->fb + rowsrc * met->font_size * vid_priv->line_length;
|
||||||
ret = vidconsole_memmove(dev, dst, src, priv->font_size *
|
ret = vidconsole_memmove(dev, dst, src, met->font_size *
|
||||||
vid_priv->line_length * count);
|
vid_priv->line_length * count);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Scroll up our position history */
|
/* Scroll up our position history */
|
||||||
diff = (rowsrc - rowdst) * priv->font_size;
|
diff = (rowsrc - rowdst) * met->font_size;
|
||||||
for (i = 0; i < priv->pos_ptr; i++)
|
for (i = 0; i < priv->pos_ptr; i++)
|
||||||
priv->pos[i].ypos -= diff;
|
priv->pos[i].ypos -= diff;
|
||||||
|
|
||||||
|
@ -202,7 +221,8 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
|
||||||
struct udevice *vid = dev->parent;
|
struct udevice *vid = dev->parent;
|
||||||
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
|
struct video_priv *vid_priv = dev_get_uclass_priv(vid);
|
||||||
struct console_tt_priv *priv = dev_get_priv(dev);
|
struct console_tt_priv *priv = dev_get_priv(dev);
|
||||||
stbtt_fontinfo *font = &priv->font;
|
struct console_tt_metrics *met = priv->cur_met;
|
||||||
|
stbtt_fontinfo *font = &met->font;
|
||||||
int width, height, xoff, yoff;
|
int width, height, xoff, yoff;
|
||||||
double xpos, x_shift;
|
double xpos, x_shift;
|
||||||
int lsb;
|
int lsb;
|
||||||
|
@ -222,7 +242,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
|
||||||
* this character */
|
* this character */
|
||||||
xpos = frac(VID_TO_PIXEL((double)x));
|
xpos = frac(VID_TO_PIXEL((double)x));
|
||||||
if (vc_priv->last_ch) {
|
if (vc_priv->last_ch) {
|
||||||
xpos += priv->scale * stbtt_GetCodepointKernAdvance(font,
|
xpos += met->scale * stbtt_GetCodepointKernAdvance(font,
|
||||||
vc_priv->last_ch, ch);
|
vc_priv->last_ch, ch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +253,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
|
||||||
* it dictates how much the cursor will move forward on the line.
|
* it dictates how much the cursor will move forward on the line.
|
||||||
*/
|
*/
|
||||||
x_shift = xpos - (double)tt_floor(xpos);
|
x_shift = xpos - (double)tt_floor(xpos);
|
||||||
xpos += advance * priv->scale;
|
xpos += advance * met->scale;
|
||||||
width_frac = (int)VID_TO_POS(xpos);
|
width_frac = (int)VID_TO_POS(xpos);
|
||||||
if (x + width_frac >= vc_priv->xsize_frac)
|
if (x + width_frac >= vc_priv->xsize_frac)
|
||||||
return -EAGAIN;
|
return -EAGAIN;
|
||||||
|
@ -252,7 +272,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
|
||||||
* image of the character. For empty characters, like ' ', data will
|
* image of the character. For empty characters, like ' ', data will
|
||||||
* return NULL;
|
* return NULL;
|
||||||
*/
|
*/
|
||||||
data = stbtt_GetCodepointBitmapSubpixel(font, priv->scale, priv->scale,
|
data = stbtt_GetCodepointBitmapSubpixel(font, met->scale, met->scale,
|
||||||
x_shift, 0, ch, &width, &height,
|
x_shift, 0, ch, &width, &height,
|
||||||
&xoff, &yoff);
|
&xoff, &yoff);
|
||||||
if (!data)
|
if (!data)
|
||||||
|
@ -262,7 +282,7 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y,
|
||||||
bits = data;
|
bits = data;
|
||||||
start = vid_priv->fb + y * vid_priv->line_length +
|
start = vid_priv->fb + y * vid_priv->line_length +
|
||||||
VID_TO_PIXEL(x) * VNBYTES(vid_priv->bpix);
|
VID_TO_PIXEL(x) * VNBYTES(vid_priv->bpix);
|
||||||
linenum = priv->baseline + yoff;
|
linenum = met->baseline + yoff;
|
||||||
if (linenum > 0)
|
if (linenum > 0)
|
||||||
start += linenum * vid_priv->line_length;
|
start += linenum * vid_priv->line_length;
|
||||||
line = start;
|
line = start;
|
||||||
|
@ -562,42 +582,78 @@ static u8 *console_truetype_find_font(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vidconsole_add_metrics() - Add a new font/size combination
|
||||||
|
*
|
||||||
|
* @dev: Video console device to update
|
||||||
|
* @font_name: Name of font
|
||||||
|
* @font_size: Size of the font (norminal pixel height)
|
||||||
|
* @font_data: Pointer to the font data
|
||||||
|
* @return 0 if OK, -EPERM if stbtt failed, -E2BIG if the the metrics table is
|
||||||
|
* full
|
||||||
|
*/
|
||||||
|
static int vidconsole_add_metrics(struct udevice *dev, const void *font_data,
|
||||||
|
uint font_size)
|
||||||
|
{
|
||||||
|
struct console_tt_priv *priv = dev_get_priv(dev);
|
||||||
|
struct console_tt_metrics *met;
|
||||||
|
stbtt_fontinfo *font;
|
||||||
|
int ascent;
|
||||||
|
|
||||||
|
if (priv->num_metrics == CONFIG_CONSOLE_TRUETYPE_MAX_METRICS)
|
||||||
|
return log_msg_ret("num", -E2BIG);
|
||||||
|
|
||||||
|
met = &priv->metrics[priv->num_metrics];
|
||||||
|
met->font_size = font_size;
|
||||||
|
met->font_data = font_data;
|
||||||
|
|
||||||
|
font = &met->font;
|
||||||
|
if (!stbtt_InitFont(font, font_data, 0)) {
|
||||||
|
debug("%s: Font init failed\n", __func__);
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pre-calculate some things we will need regularly */
|
||||||
|
met->scale = stbtt_ScaleForPixelHeight(font, font_size);
|
||||||
|
stbtt_GetFontVMetrics(font, &ascent, 0, 0);
|
||||||
|
met->baseline = (int)(ascent * met->scale);
|
||||||
|
|
||||||
|
return priv->num_metrics++;
|
||||||
|
}
|
||||||
|
|
||||||
static int console_truetype_probe(struct udevice *dev)
|
static int console_truetype_probe(struct udevice *dev)
|
||||||
{
|
{
|
||||||
struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
|
struct vidconsole_priv *vc_priv = dev_get_uclass_priv(dev);
|
||||||
struct console_tt_priv *priv = dev_get_priv(dev);
|
struct console_tt_priv *priv = dev_get_priv(dev);
|
||||||
struct udevice *vid_dev = dev->parent;
|
struct udevice *vid_dev = dev->parent;
|
||||||
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
|
struct video_priv *vid_priv = dev_get_uclass_priv(vid_dev);
|
||||||
stbtt_fontinfo *font = &priv->font;
|
void *font_data;
|
||||||
int ascent;
|
uint font_size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
debug("%s: start\n", __func__);
|
debug("%s: start\n", __func__);
|
||||||
if (vid_priv->font_size)
|
if (vid_priv->font_size)
|
||||||
priv->font_size = vid_priv->font_size;
|
font_size = vid_priv->font_size;
|
||||||
else
|
else
|
||||||
priv->font_size = CONFIG_CONSOLE_TRUETYPE_SIZE;
|
font_size = CONFIG_CONSOLE_TRUETYPE_SIZE;
|
||||||
priv->font_data = console_truetype_find_font();
|
font_data = console_truetype_find_font();
|
||||||
if (!priv->font_data) {
|
if (!font_data) {
|
||||||
debug("%s: Could not find any fonts\n", __func__);
|
debug("%s: Could not find any fonts\n", __func__);
|
||||||
return -EBFONT;
|
return -EBFONT;
|
||||||
}
|
}
|
||||||
|
|
||||||
vc_priv->x_charsize = priv->font_size;
|
ret = vidconsole_add_metrics(dev, font_data, font_size);
|
||||||
vc_priv->y_charsize = priv->font_size;
|
if (ret < 0)
|
||||||
|
return log_msg_ret("add", ret);
|
||||||
|
priv->cur_met = &priv->metrics[ret];
|
||||||
|
|
||||||
|
vc_priv->x_charsize = font_size;
|
||||||
|
vc_priv->y_charsize = font_size;
|
||||||
vc_priv->xstart_frac = VID_TO_POS(2);
|
vc_priv->xstart_frac = VID_TO_POS(2);
|
||||||
vc_priv->cols = vid_priv->xsize / priv->font_size;
|
vc_priv->cols = vid_priv->xsize / font_size;
|
||||||
vc_priv->rows = vid_priv->ysize / priv->font_size;
|
vc_priv->rows = vid_priv->ysize / font_size;
|
||||||
vc_priv->tab_width_frac = VID_TO_POS(priv->font_size) * 8 / 2;
|
vc_priv->tab_width_frac = VID_TO_POS(font_size) * 8 / 2;
|
||||||
|
|
||||||
if (!stbtt_InitFont(font, priv->font_data, 0)) {
|
|
||||||
debug("%s: Font init failed\n", __func__);
|
|
||||||
return -EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pre-calculate some things we will need regularly */
|
|
||||||
priv->scale = stbtt_ScaleForPixelHeight(font, priv->font_size);
|
|
||||||
stbtt_GetFontVMetrics(font, &ascent, 0, 0);
|
|
||||||
priv->baseline = (int)(ascent * priv->scale);
|
|
||||||
debug("%s: ready\n", __func__);
|
debug("%s: ready\n", __func__);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in a new issue