#define MODULE "text" #include "render/TextRenderer.h" #include "bootboot.h" #include "init/InitRD.h" #include "io/Serial.h" #include "log/Log.h" #include "psf2.h" #include "render/Framebuffer.h" #include "std/stdio.h" #include "std/string.h" extern BOOTBOOT bootboot; static psf2_t* font; static Color bgColor = Color::Black; static Color fgColor = Color::White; static uint32_t xpos = 0; static uint32_t ypos = 0; bool TextRenderer::try_initialize() { InitRD::File font_file = InitRD::open("boot/font.psf"); if (!font_file.addr) { kerrorln("Failed to load boot/font.psf from initrd"); return false; } font = (psf2_t*)font_file.addr; if (font->magic != PSF_FONT_MAGIC) { kerrorln("Font magic does not match PSF font magic: %x", font->magic); return false; } return true; } bool TextRenderer::is_initialized() { return font; // if font is NULL, not initialized, else yes } static void putchar_at_offset(char c, int cx, int cy, Color& fg, Color& bg) { uint8_t* glyph = (uint8_t*)font + font->headersize + (c > 0 && (uint32_t)c < font->numglyph ? c : 0) * font->bytesperglyph; int mask; for (uint32_t y = 0; y < font->height; y++) { mask = 1 << (font->width - 1); for (uint32_t x = 0; x < font->width; x++) { framebuffer0.set_pixel(cx + x, cy + y, *((uint32_t*)glyph) & mask ? fg : bg); mask >>= 1; } } } void TextRenderer::putchar(char chr) { switch (chr) { case '\n': ypos += font->height; if ((ypos + font->height) >= bootboot.fb_height) { memcpy((void*)bootboot.fb_ptr, (uint32_t*)bootboot.fb_ptr + (bootboot.fb_scanline * font->height), bootboot.fb_size - (sizeof(uint32_t) * bootboot.fb_scanline * font->height)); ypos -= font->height; framebuffer0.paint_rect(0, ypos, bootboot.fb_width, font->height, Color::Black); } xpos = 0; break; case '\r': xpos = 0; break; case '\b': if (xpos != 0) { xpos -= font->width + 1; framebuffer0.paint_rect(xpos, ypos, font->width + 1, font->height, Color::Black); } break; default: putchar_at_offset(chr, xpos, ypos, fgColor, bgColor); xpos += font->width + 1; if ((xpos + font->width + 1) > bootboot.fb_width) { xpos = 0; ypos += font->height; if (ypos > bootboot.fb_height) { memcpy((void*)bootboot.fb_ptr, (uint32_t*)bootboot.fb_ptr + (bootboot.fb_scanline * font->height), bootboot.fb_size - (sizeof(uint32_t) * bootboot.fb_scanline * font->height)); ypos -= font->height; framebuffer0.paint_rect(0, ypos, bootboot.fb_width, font->height, Color::Black); } } break; } } void TextRenderer::write(const char* str, size_t size) { for (size_t i = 0; i < size; i++) { putchar(str[i]); } }