From 31afd2a2540430139200e50fd9cf546dc93fbfa9 Mon Sep 17 00:00:00 2001 From: lvntky Date: Tue, 26 Nov 2024 01:46:12 +0300 Subject: [feature] font rendering updated, but not works --- CMakeLists.txt | 4 +- asset/font/tamsyn.psf | Bin 0 -> 4421 bytes asset/font/tamzen_font.psf | Bin 0 -> 4970 bytes examples/empty_example.c | 53 ------------- examples/text.c | 28 +++++++ fbgl.h | 187 +++++++++++++++++++++++++++------------------ 6 files changed, 141 insertions(+), 131 deletions(-) create mode 100644 asset/font/tamsyn.psf create mode 100644 asset/font/tamzen_font.psf delete mode 100644 examples/empty_example.c create mode 100644 examples/text.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 02aa36d..10cb5e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,10 +23,10 @@ function(add_example NAME) add_dependencies(run-examples "run_${NAME}") endfunction() -add_example(empty_example) add_example(line) add_example(rectangle) add_example(red) add_example(texture) add_example(raw_mode) -add_example(framebuf_info) \ No newline at end of file +add_example(framebuf_info) +add_example(text) diff --git a/asset/font/tamsyn.psf b/asset/font/tamsyn.psf new file mode 100644 index 0000000..0054a2b Binary files /dev/null and b/asset/font/tamsyn.psf differ diff --git a/asset/font/tamzen_font.psf b/asset/font/tamzen_font.psf new file mode 100644 index 0000000..6cfe468 Binary files /dev/null and b/asset/font/tamzen_font.psf differ diff --git a/examples/empty_example.c b/examples/empty_example.c deleted file mode 100644 index 352824a..0000000 --- a/examples/empty_example.c +++ /dev/null @@ -1,53 +0,0 @@ -#define FBGL_IMPLEMENTATION -//#define FBGL_HIDE_CURSOR -#define FBGL_USE_FREETYPE -#include "fbgl.h" - -#include -#include - -int main() -{ - printf("version %s\n", fbgl_version_info()); - printf("name %s\n", fbgl_name_info()); - - fbgl_t buffer; - if (fbgl_init("/dev/fb0", &buffer) == -1) { - fprintf(stdout, "Error: could not open framebuffer device\n"); - return -1; - } - int color = 0x00000000; - - FT_Library library = fbgl_freetype_init(); - if (!library) { - fbgl_destroy(&buffer); - return -1; - } - - FT_Face face = fbgl_load_font(library, "../asset/font_2.ttf", - 24); // Adjust path and size - if (!face) { - fbgl_freetype_cleanup(library); - fbgl_destroy(&buffer); - return -1; - } - - // Render text to framebuffer - fbgl_render_freetype_text(&buffer, library, face, "Hello, World!", 50, - 50); - - // Main loop checking for ESC key - int l = 0; - while (1) { - if (fbgl_check_esc_key()) { - fprintf(stdout, "ESC pressed\n"); - break; - } - //fbgl_set_bg(&buffer, i++); // Set background color to - for (int i = 0x000000; i <= 0xFFFFFF; i++) { - fbgl_set_bg(&buffer, i); - } - } - fbgl_destroy(&buffer); - return 0; -} diff --git a/examples/text.c b/examples/text.c new file mode 100644 index 0000000..0982a37 --- /dev/null +++ b/examples/text.c @@ -0,0 +1,28 @@ +#define FBGL_IMPLEMENTATION +#include "fbgl.h" +#include +#include +#include // for usleep +#include + +int main(int argc, char *argv[]) +{ + fbgl_t buf; + fbgl_init("/dev/fb0", &buf); + + fbgl_set_bg(&buf, 0x000000); + + fbgl_psf2_font_t *font = fbgl_load_psf2_font(argv[1]); + + size_t framerate = 30 * 30; + fbgl_render_psf2_text(&buf, font, "hello fbgl", 100, 100, 0xFFFFFF); + + for(size_t i = 0; i < framerate; i++) { + usleep(50000); + } + + fbgl_destroy_psf2_font(font); + fbgl_destroy(&buf); + + return 0; +} diff --git a/fbgl.h b/fbgl.h index 03dd073..51342f6 100644 --- a/fbgl.h +++ b/fbgl.h @@ -15,7 +15,7 @@ // // Contributors: // @lvntky -// @dario-loi +// @dario-loi // // LICENSE // @@ -70,18 +70,6 @@ typedef struct fbgl_window { fbgl_t *fb; // Pointer to the framebuffer context } fbgl_window_t; -typedef struct fbgl_psf2_header { - uint8_t magic[2]; // Magic number, should be {0x72, 0xB5} - uint8_t version; // Version of PSF2 (usually 0) - uint8_t header_size; // Size of the header (usually 32 bytes) - uint16_t flags; // Flags (usually 0) - uint16_t numglyphs; // Number of glyphs (characters) - uint16_t bytes_per_glyph; // Number of bytes per glyph (depends on font size) - uint16_t height; // Height of each character in pixels - uint16_t width; // Width of each character in pixels - uint8_t *glyphs; // Pointer to the glyph data -} fbgl_psf2_header_t; - typedef struct fbgl_point { int32_t x; int32_t y; @@ -93,6 +81,18 @@ typedef struct fbgl_tga_texture { uint32_t *data; } fbgl_tga_texture_t; +typedef struct fbgl_psf2_font { + uint32_t magic; // Magic number: 0x864ab572 + uint32_t version; // PSF version (should be 0) + uint32_t headersize; // Offset of the bitmaps in the file + uint32_t flags; // Font flags + uint32_t glyph_count; // Number of glyphs + uint32_t glyph_size; // Bytes per glyph + uint32_t char_width; // Glyph width in pixels + uint32_t char_height; // Glyph height in pixels + uint8_t *glyphs; // Pointer to glyph data +} fbgl_psf2_font_t; + typedef struct fbgl_keyboard { bool keys[FBGL_MAX_KEYS]; // Current state of each key bool prev_keys[FBGL_MAX_KEYS]; // Previous state of each key @@ -128,15 +128,6 @@ int fbgl_hide_cursor(int fd) } #endif // FBGL_HIDE_CURSOR -#ifdef FBGL_USE_FREETYPE -FT_Library fbgl_freetype_init(void); -void fbgl_freetype_cleanup(FT_Library library); -FT_Face fbgl_load_font(FT_Library library, const char *font_path, - int font_size); -void fbgl_render_freetype_text(fbgl_t *fb, FT_Library library, FT_Face face, - const char *text, int x, int y); -#endif // FBGL_USE_FREETYPE - #ifdef __cplusplus extern "C" { #endif @@ -189,6 +180,13 @@ void fbgl_destroy_texture(fbgl_tga_texture_t *texture); void fbgl_draw_texture(fbgl_t *fb, fbgl_tga_texture_t const *texture, int32_t x, int32_t y); +/** +* Text +*/ +fbgl_psf2_font_t *fbgl_load_psf2_font(const char *path); +void fbgl_destroy_psf2_font(fbgl_psf2_font_t *font); +void fbgl_render_psf2_text(fbgl_t *fb, fbgl_psf2_font_t *font, const char *text, + int x, int y, uint32_t color); /** * Keyboard */ @@ -380,60 +378,6 @@ void fbgl_set_signal_handlers(void) } } -#ifdef FBGL_USE_FREETYPE -FT_Library fbgl_freetype_init(void) -{ - FT_Library library; - if (FT_Init_FreeType(&library)) { - fprintf(stderr, "Could not init FreeType Library\n"); - return NULL; - } - return library; -} - -void fbgl_freetype_cleanup(FT_Library library) -{ - if (library) { - FT_Done_FreeType(library); - } -} - -FT_Face fbgl_load_font(FT_Library library, const char *font_path, int font_size) -{ - FT_Face face; - if (FT_New_Face(library, font_path, 0, &face)) { - fprintf(stderr, "Could not open font: %s\n", font_path); - return NULL; - } - FT_Set_Pixel_Sizes(face, 0, font_size); // Set font size - return face; -} - -void fbgl_render_freetype_text(fbgl_t *fb, FT_Library library, FT_Face face, - const char *text, int32_t x, int32_t y) -{ - while (*text) { - FT_Load_Char(face, *text, FT_LOAD_RENDER); - FT_Bitmap bitmap = face->glyph->bitmap; - - // Draw the bitmap to framebuffer - for (uint32_t j = 0; j < bitmap.rows; j++) { - for (uint32_t i = 0; i < bitmap.width; i++) { - if (bitmap.buffer[j * bitmap.width + - i]) { // Check pixel is not empty - fbgl_put_pixel(x + i, y + j, 0xFF0000, - fb); // Draw white pixel - } - } - } - x += face->glyph->advance.x >> - 6; // Move to the next character position - ++text; - } -} - -#endif // FBGL_USE_FREETYPE - void fbgl_draw_line(fbgl_point_t x, fbgl_point_t y, uint32_t color, fbgl_t *buffer) { @@ -681,6 +625,97 @@ float fbgl_get_fps(void) return 0.0f; // Avoid division by zero } } +fbgl_psf2_font_t *fbgl_load_psf2_font(const char *path) +{ + FILE *file = fopen(path, "rb"); + if (!file) { + perror("Failed to open font file"); + return NULL; + } + + // Read the PSF2 header + fbgl_psf2_font_t *font = malloc(sizeof(fbgl_psf2_font_t)); + if (!font) { + perror("Failed to allocate memory for font"); + fclose(file); + return NULL; + } + + if (fread(font, sizeof(uint32_t), 8, file) != 8) { + perror("Failed to read font header"); + free(font); + fclose(file); + return NULL; + } + /* + // Verify the magic number + if (font->magic != 0x864ab572) { + fprintf(stderr, "Invalid PSF2 magic number\n"); + free(font); + fclose(file); + return NULL; + } + */ + // Load glyphs + font->glyphs = malloc(font->glyph_count * font->glyph_size); + if (!font->glyphs) { + perror("Failed to allocate memory for glyphs"); + free(font); + fclose(file); + return NULL; + } + + if (fread(font->glyphs, font->glyph_size, font->glyph_count, file) != + font->glyph_count) { + perror("Failed to read glyph data"); + free(font->glyphs); + free(font); + fclose(file); + return NULL; + } + + fclose(file); + return font; +} +void fbgl_destroy_psf2_font(fbgl_psf2_font_t *font) +{ + if (font) { + free(font->glyphs); + free(font); + } +} +void fbgl_render_psf2_text(fbgl_t *fb, fbgl_psf2_font_t *font, const char *text, + int x, int y, uint32_t color) +{ + if (!fb || !font || !text) + return; + + int cursor_x = x, cursor_y = y; + + for (const char *c = text; *c; c++) { + uint32_t glyph_index = (uint8_t)*c; + + if (glyph_index >= font->glyph_count) { + glyph_index = + 0; // Use a fallback glyph (e.g., space or undefined) + } + + uint8_t *glyph = font->glyphs + glyph_index * font->glyph_size; + + for (uint32_t row = 0; row < font->char_height; row++) { + for (uint32_t col = 0; col < font->char_width; col++) { + if (glyph[row] & + (1 << (font->char_width - 1 - col))) { + fbgl_put_pixel(cursor_x + col, + cursor_y + row, color, + fb); + } + } + } + + cursor_x += font->char_width; // Move to the next character + } +} #endif // FBGL_IMPLEMENTATION -- cgit v1.2.3