123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- #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;
- }
|