Luna/kernel/src/render/TextRenderer.cpp

101 lines
2.9 KiB
C++
Raw Normal View History

2022-09-05 16:13:51 +02:00
#include "render/TextRenderer.h"
#include "bootboot.h"
#include "init/InitRD.h"
#include "io/Serial.h"
#include "psf2.h"
2022-09-10 18:44:14 +02:00
#include "render/Framebuffer.h"
2022-09-05 16:13:51 +02:00
#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::find_file("boot/font.psf");
if (!font_file.addr)
{
Serial::println("Failed to load boot/font.psf from initrd");
return false;
}
font = (psf2_t*)font_file.addr;
if (font->magic != PSF_FONT_MAGIC)
{
Serial::println("Font magic does not match PSF 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++)
{
2022-09-10 18:44:14 +02:00
framebuffer0.set_pixel(cx + x, cy + y, *((uint32_t*)glyph) & mask ? fg : bg);
2022-09-05 16:13:51 +02:00
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;
2022-09-10 18:44:14 +02:00
framebuffer0.paint_rect(0, ypos, bootboot.fb_width, font->height, Color::Black);
2022-09-05 16:13:51 +02:00
}
xpos = 0;
break;
case '\r': xpos = 0; break;
case '\b':
if (xpos != 0)
{
xpos -= font->width + 1;
2022-09-10 18:44:14 +02:00
framebuffer0.paint_rect(xpos, ypos, font->width + 1, font->height, Color::Black);
2022-09-05 16:13:51 +02:00
}
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;
2022-09-10 18:44:14 +02:00
framebuffer0.paint_rect(0, ypos, bootboot.fb_width, font->height, Color::Black);
2022-09-05 16:13:51 +02:00
}
}
break;
}
}
void TextRenderer::write(const char* str, size_t size)
{
for (size_t i = 0; i < size; i++) { putchar(str[i]); }
}