mirror of
https://gitlab.com/bztsrc/posix-uefi.git
synced 2025-01-01 03:25:52 +01:00
118 lines
4 KiB
C
118 lines
4 KiB
C
#include <uefi.h>
|
|
|
|
/* Scalable Screen Font (https://gitlab.com/bztsrc/scalable-font2) */
|
|
typedef struct {
|
|
unsigned char magic[4];
|
|
unsigned int size;
|
|
unsigned char type;
|
|
unsigned char features;
|
|
unsigned char width;
|
|
unsigned char height;
|
|
unsigned char baseline;
|
|
unsigned char underline;
|
|
unsigned short fragments_offs;
|
|
unsigned int characters_offs;
|
|
unsigned int ligature_offs;
|
|
unsigned int kerning_offs;
|
|
unsigned int cmap_offs;
|
|
} __attribute__((packed)) ssfn_font_t;
|
|
|
|
/* framebuffer properties */
|
|
unsigned int width, height, pitch;
|
|
unsigned char *lfb;
|
|
/* font to be used */
|
|
ssfn_font_t *font;
|
|
|
|
/**
|
|
* Display string using a bitmap font without the SSFN library
|
|
*/
|
|
void printString(int x, int y, char *s)
|
|
{
|
|
unsigned char *ptr, *chr, *frg;
|
|
unsigned int c;
|
|
uintptr_t o, p;
|
|
int i, j, k, l, m, n;
|
|
while(*s) {
|
|
c = 0; s += mbtowc((wchar_t*)&c, (const char*)s, 4);
|
|
if(c == '\r') { x = 0; continue; } else
|
|
if(c == '\n') { x = 0; y += font->height; continue; }
|
|
for(ptr = (unsigned char*)font + font->characters_offs, chr = 0, i = 0; i < 0x110000; i++) {
|
|
if(ptr[0] == 0xFF) { i += 65535; ptr++; }
|
|
else if((ptr[0] & 0xC0) == 0xC0) { j = (((ptr[0] & 0x3F) << 8) | ptr[1]); i += j; ptr += 2; }
|
|
else if((ptr[0] & 0xC0) == 0x80) { j = (ptr[0] & 0x3F); i += j; ptr++; }
|
|
else { if((unsigned int)i == c) { chr = ptr; break; } ptr += 6 + ptr[1] * (ptr[0] & 0x40 ? 6 : 5); }
|
|
}
|
|
if(!chr) continue;
|
|
ptr = chr + 6; o = (uintptr_t)lfb + y * pitch + x * 4;
|
|
for(i = n = 0; i < chr[1]; i++, ptr += chr[0] & 0x40 ? 6 : 5) {
|
|
if(ptr[0] == 255 && ptr[1] == 255) continue;
|
|
frg = (unsigned char*)font + (chr[0] & 0x40 ? ((ptr[5] << 24) | (ptr[4] << 16) | (ptr[3] << 8) | ptr[2]) :
|
|
((ptr[4] << 16) | (ptr[3] << 8) | ptr[2]));
|
|
if((frg[0] & 0xE0) != 0x80) continue;
|
|
o += (int)(ptr[1] - n) * pitch; n = ptr[1];
|
|
k = ((frg[0] & 0x1F) + 1) << 3; j = frg[1] + 1; frg += 2;
|
|
for(m = 1; j; j--, n++, o += pitch)
|
|
for(p = o, l = 0; l < k; l++, p += 4, m <<= 1) {
|
|
if(m > 0x80) { frg++; m = 1; }
|
|
if(*frg & m) *((unsigned int*)p) = 0xFFFFFF;
|
|
}
|
|
}
|
|
x += chr[4]+1; y += chr[5];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Display bitmap fonts
|
|
*/
|
|
int main(int argc, char **argv)
|
|
{
|
|
efi_status_t status;
|
|
efi_guid_t gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
|
|
efi_gop_t *gop = NULL;
|
|
FILE *f;
|
|
long int size;
|
|
|
|
/* load font */
|
|
if((f = fopen("\\0A_bmpfont\\font.sfn", "r"))) {
|
|
fseek(f, 0, SEEK_END);
|
|
size = ftell(f);
|
|
fseek(f, 0, SEEK_SET);
|
|
font = (ssfn_font_t*)malloc(size + 1);
|
|
if(!font) {
|
|
fprintf(stderr, "unable to allocate memory\n");
|
|
return 1;
|
|
}
|
|
fread(font, size, 1, f);
|
|
fclose(f);
|
|
} else {
|
|
fprintf(stderr, "Unable to load font\n");
|
|
return 0;
|
|
}
|
|
|
|
/* set video mode */
|
|
status = BS->LocateProtocol(&gopGuid, NULL, (void**)&gop);
|
|
if(!EFI_ERROR(status) && gop) {
|
|
status = gop->SetMode(gop, 0);
|
|
ST->ConOut->Reset(ST->ConOut, 0);
|
|
ST->StdErr->Reset(ST->StdErr, 0);
|
|
if(EFI_ERROR(status)) {
|
|
fprintf(stderr, "unable to set video mode\n");
|
|
return 0;
|
|
}
|
|
/* set up destination buffer */
|
|
lfb = (unsigned char*)gop->Mode->FrameBufferBase;
|
|
width = gop->Mode->Information->HorizontalResolution;
|
|
height = gop->Mode->Information->VerticalResolution;
|
|
pitch = sizeof(unsigned int) * gop->Mode->Information->PixelsPerScanLine;
|
|
} else {
|
|
fprintf(stderr, "unable to get graphics output protocol\n");
|
|
return 0;
|
|
}
|
|
|
|
/* display multilingual text */
|
|
printString(10, 10, "Hello 多种语言 Многоязычный többnyelvű World!");
|
|
|
|
/* free resources exit */
|
|
free(font);
|
|
return 0;
|
|
}
|