From ef24db793b8bc3372feb674e7bf1d785d8697bc1 Mon Sep 17 00:00:00 2001 From: lvntky Date: Tue, 26 Nov 2024 10:49:07 +0300 Subject: [feature] font rendering done --- CMakeLists.txt | 1 + asset/font/font-16.psf | Bin 0 -> 10310 bytes examples/text.c | 26 +++++++ fbgl.h | 198 +++++++++++++++++++++++++------------------------ 4 files changed, 130 insertions(+), 95 deletions(-) create mode 100644 asset/font/font-16.psf create mode 100644 examples/text.c diff --git a/CMakeLists.txt b/CMakeLists.txt index be2849b..10cb5e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,3 +29,4 @@ add_example(red) add_example(texture) add_example(raw_mode) add_example(framebuf_info) +add_example(text) diff --git a/asset/font/font-16.psf b/asset/font/font-16.psf new file mode 100644 index 0000000..4b68ed1 Binary files /dev/null and b/asset/font/font-16.psf differ diff --git a/examples/text.c b/examples/text.c new file mode 100644 index 0000000..41e3560 --- /dev/null +++ b/examples/text.c @@ -0,0 +1,26 @@ +#define FBGL_IMPLEMENTATION +#include "fbgl.h" +#include +#include +#include // for usleep +#include + +int main(int argc, char *argv[]) +{ + fbgl_t fb; + fbgl_init("/dev/fb0", &fb); + + fbgl_set_bg(&fb, 0xFFFFFF); + + fbgl_psf1_font_t *font = fbgl_load_psf1_font(argv[1]); + fbgl_render_psf1_text(&fb, font, "hello, fbgl", 100, 100, 0x000000); + size_t framerate = 30 * 30; + + for(size_t i = 0; i < framerate; i++) { + usleep(50000); + } + fbgl_destroy_psf1_font(font); + fbgl_destroy(&fb); + + return 0; +} diff --git a/fbgl.h b/fbgl.h index 1edf676..f34bca0 100644 --- a/fbgl.h +++ b/fbgl.h @@ -82,12 +82,12 @@ typedef struct fbgl_tga_texture { } fbgl_tga_texture_t; typedef struct fbgl_psf1_font { - uint8_t magic[2]; // Magic number (0x36, 0x04 for PSF1) - uint8_t mode; // Mode (0 = 256 glyphs, 1 = 512 glyphs) - uint8_t char_height; // Character height in pixels - uint8_t *glyphs; // Pointer to glyph data - uint16_t glyph_count; // Number of glyphs (calculated from mode) - uint16_t char_width; // Character width in pixels (always 8 for PSF1) + uint8_t magic[2]; // Magic number (0x36, 0x04 for PSF1) + uint8_t mode; // Mode (0 = 256 glyphs, 1 = 512 glyphs) + uint8_t char_height; // Character height in pixels + uint8_t *glyphs; // Pointer to glyph data + uint16_t glyph_count; // Number of glyphs (calculated from mode) + uint16_t char_width; // Character width in pixels (always 8 for PSF1) } fbgl_psf1_font_t; typedef struct fbgl_keyboard { @@ -623,107 +623,115 @@ float fbgl_get_fps(void) } } -fbgl_psf1_font_t *fbgl_load_psf1_font(const char *path) { - FILE *file = fopen(path, "rb"); - if (!file) { - perror("Failed to open font file"); - return NULL; - } - - // Allocate memory for the font structure - fbgl_psf1_font_t *font = malloc(sizeof(fbgl_psf1_font_t)); - if (!font) { - perror("Failed to allocate memory for font"); - fclose(file); - return NULL; - } - - // Read the header (4 bytes) - uint8_t header[4]; - if (fread(header, 1, sizeof(header), file) != sizeof(header)) { - perror("Failed to read font header"); - free(font); - fclose(file); - return NULL; - } - - // Verify magic number - if (header[0] != 0x36 || header[1] != 0x04) { - fprintf(stderr, "Invalid PSF1 magic number\n"); - free(font); - fclose(file); - return NULL; - } - - // Populate the font structure - font->magic[0] = header[0]; - font->magic[1] = header[1]; - font->mode = header[2]; - font->char_height = header[3]; - font->glyph_count = (font->mode & 0x01) ? 512 : 256; // Determine glyph count - font->char_width = 8; // PSF1 glyphs are always 8 pixels wide - - // Allocate memory for glyphs - size_t glyph_data_size = font->glyph_count * font->char_height; - font->glyphs = malloc(glyph_data_size); - if (!font->glyphs) { - perror("Failed to allocate memory for glyphs"); - free(font); - fclose(file); - return NULL; - } - - // Read glyph data - if (fread(font->glyphs, 1, glyph_data_size, file) != glyph_data_size) { - perror("Failed to read glyph data"); - free(font->glyphs); - free(font); - fclose(file); - return NULL; - } - - fclose(file); - return font; +fbgl_psf1_font_t *fbgl_load_psf1_font(const char *path) +{ + FILE *file = fopen(path, "rb"); + if (!file) { + perror("Failed to open font file"); + return NULL; + } + + // Allocate memory for the font structure + fbgl_psf1_font_t *font = malloc(sizeof(fbgl_psf1_font_t)); + if (!font) { + perror("Failed to allocate memory for font"); + fclose(file); + return NULL; + } + + // Read the header (4 bytes) + uint8_t header[4]; + if (fread(header, 1, sizeof(header), file) != sizeof(header)) { + perror("Failed to read font header"); + free(font); + fclose(file); + return NULL; + } + + // Verify magic number + if (header[0] != 0x36 || header[1] != 0x04) { + fprintf(stderr, "Invalid PSF1 magic number\n"); + free(font); + fclose(file); + return NULL; + } + + // Populate the font structure + font->magic[0] = header[0]; + font->magic[1] = header[1]; + font->mode = header[2]; + font->char_height = header[3]; + font->glyph_count = (font->mode & 0x01) ? 512 : + 256; // Determine glyph count + font->char_width = 8; // PSF1 glyphs are always 8 pixels wide + + // Allocate memory for glyphs + size_t glyph_data_size = font->glyph_count * font->char_height; + font->glyphs = malloc(glyph_data_size); + if (!font->glyphs) { + perror("Failed to allocate memory for glyphs"); + free(font); + fclose(file); + return NULL; + } + + // Read glyph data + if (fread(font->glyphs, 1, glyph_data_size, file) != glyph_data_size) { + perror("Failed to read glyph data"); + free(font->glyphs); + free(font); + fclose(file); + return NULL; + } + + fclose(file); + return font; } -void fbgl_destroy_psf1_font(fbgl_psf1_font_t *font) { - if (font) { - free(font->glyphs); - free(font); - } +void fbgl_destroy_psf1_font(fbgl_psf1_font_t *font) +{ + if (font) { + free(font->glyphs); + free(font); + } } -void fbgl_render_psf1_text(fbgl_t *fb, fbgl_psf1_font_t *font, const char *text, int x, int y, uint32_t color) { - if (!fb || !font || !text) return; +void fbgl_render_psf1_text(fbgl_t *fb, fbgl_psf1_font_t *font, const char *text, + int x, int y, uint32_t color) +{ + if (!fb || !font || !text) + return; - int cursor_x = x; - int cursor_y = y; + int cursor_x = x; + int cursor_y = y; - for (const char *c = text; *c; c++) { - uint8_t glyph_index = (uint8_t)*c; + for (const char *c = text; *c; c++) { + uint8_t glyph_index = (uint8_t)*c; - // Ensure glyph index is within range - if (glyph_index >= font->glyph_count) glyph_index = 0; // Default to space or undefined glyph + // Ensure glyph index is within range + if (glyph_index >= font->glyph_count) + glyph_index = 0; // Default to space or undefined glyph - // Locate the glyph in the glyph table - uint8_t *glyph = font->glyphs + glyph_index * font->char_height; + // Locate the glyph in the glyph table + uint8_t *glyph = font->glyphs + glyph_index * font->char_height; - // Render the glyph - for (int row = 0; row < font->char_height; row++) { - for (int col = 0; col < font->char_width; col++) { - // Check if the bit is set in the glyph - if (glyph[row] & (0x80 >> col)) { - fbgl_put_pixel(cursor_x + col, cursor_y + row, color, fb); - } - } - } + // Render the glyph + for (int row = 0; row < font->char_height; row++) { + for (int col = 0; col < font->char_width; col++) { + // Check if the bit is set in the glyph + if (glyph[row] & (0x80 >> col)) { + fbgl_put_pixel(cursor_x + col, + cursor_y + row, color, + fb); + } + } + } - // Move to the next character position - cursor_x += font->char_width; - } + // Move to the next character position + cursor_x += font->char_width; + } } - #endif // FBGL_IMPLEMENTATION #ifdef __cplusplus -- cgit v1.2.3