mirror of https://github.com/ipxe/ipxe.git
[efi] Support Unicode character output via framebuffer console
Extend the glyph cache to include a number of dynamic entries that are populated on demand whenever a non-ASCII character needs to be drawn. Signed-off-by: Michael Brown <mcb30@ipxe.org>pull/631/head
parent
ba93c9134c
commit
dd35475438
|
@ -65,6 +65,9 @@ struct console_driver efi_console __attribute__ (( weak ));
|
|||
/** Number of ASCII glyphs in cache */
|
||||
#define EFIFB_ASCII 128
|
||||
|
||||
/** Number of dynamic non-ASCII glyphs in cache */
|
||||
#define EFIFB_DYNAMIC 32
|
||||
|
||||
/* Forward declaration */
|
||||
struct console_driver efifb_console __console_driver;
|
||||
|
||||
|
@ -89,6 +92,10 @@ struct efifb {
|
|||
struct fbcon_font font;
|
||||
/** Character glyph cache */
|
||||
userptr_t glyphs;
|
||||
/** Dynamic characters in cache */
|
||||
unsigned int dynamic[EFIFB_DYNAMIC];
|
||||
/** Next dynamic character cache entry to evict */
|
||||
unsigned int next;
|
||||
};
|
||||
|
||||
/** The EFI frame buffer */
|
||||
|
@ -177,6 +184,41 @@ static int efifb_draw_unknown ( unsigned int index ) {
|
|||
return efifb_draw ( '?', index, -1U );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dynamic glyph index
|
||||
*
|
||||
* @v character Unicode character
|
||||
* @ret index Glyph cache index
|
||||
*/
|
||||
static unsigned int efifb_dynamic ( unsigned int character ) {
|
||||
unsigned int dynamic;
|
||||
unsigned int index;
|
||||
unsigned int i;
|
||||
int height;
|
||||
|
||||
/* Search existing cached entries */
|
||||
for ( i = 0 ; i < EFIFB_DYNAMIC ; i++ ) {
|
||||
if ( character == efifb.dynamic[i] )
|
||||
return ( EFIFB_ASCII + i );
|
||||
}
|
||||
|
||||
/* Overwrite the oldest cache entry */
|
||||
dynamic = ( efifb.next++ % EFIFB_DYNAMIC );
|
||||
index = ( EFIFB_ASCII + dynamic );
|
||||
DBGC2 ( &efifb, "EFIFB dynamic %#02x is glyph %#02x\n",
|
||||
dynamic, character );
|
||||
|
||||
/* Draw glyph */
|
||||
height = efifb_draw ( character, index, 0 );
|
||||
if ( height < 0 )
|
||||
efifb_draw_unknown ( index );
|
||||
|
||||
/* Record cached character */
|
||||
efifb.dynamic[dynamic] = character;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get character glyph
|
||||
*
|
||||
|
@ -195,8 +237,8 @@ static void efifb_glyph ( unsigned int character, uint8_t *glyph ) {
|
|||
|
||||
} else {
|
||||
|
||||
/* Non-ASCII character: use an "unknown" glyph */
|
||||
index = 0;
|
||||
/* Non-ASCII character: use dynamic glyph cache */
|
||||
index = efifb_dynamic ( character );
|
||||
}
|
||||
|
||||
/* Copy cached glyph */
|
||||
|
@ -248,7 +290,7 @@ static int efifb_glyphs ( void ) {
|
|||
efifb.font.height = max;
|
||||
|
||||
/* Allocate glyph data */
|
||||
len = ( EFIFB_ASCII * efifb.font.height );
|
||||
len = ( ( EFIFB_ASCII + EFIFB_DYNAMIC ) * efifb.font.height );
|
||||
efifb.glyphs = umalloc ( len );
|
||||
if ( ! efifb.glyphs ) {
|
||||
rc = -ENOMEM;
|
||||
|
@ -273,6 +315,9 @@ static int efifb_glyphs ( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Clear dynamic glyph character cache */
|
||||
memset ( efifb.dynamic, 0, sizeof ( efifb.dynamic ) );
|
||||
|
||||
efifb.font.glyph = efifb_glyph;
|
||||
return 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue