From 8a347f9515a0021361549016e86fcca159c948f5 Mon Sep 17 00:00:00 2001 From: dario-loi Date: Sun, 24 Nov 2024 17:33:45 +0100 Subject: Working CMakeLists.txt and many bugfixes Provided a working CMakeLists.txt file to build all of the examples, also fixed a bunch of bugs (some fixes also depend on personal preference and should be reviewed by maintainers): 1. Switched fbgl_t types from size_t to uint32_t as there is no way a screen resolution will be more than 2^32, this way we save 4 bytes and we have faster comparisons 2. Used int32_t instead of int for better clarity 3. fbgl_point now uses int32_t instead of uint32_t, no more sign comparison warnings (for loops that worked with fbgl_point were already working with int32_t in practice) 4. line.c now uses usleep(1000) to wait inbetween individual line draws instead of an empty for loop, as that was optimized away in release builds and led to all the animation being played instantly 5. removed the void fbgl_set_bg() forward declaration as it was incorrect w.r.t the actual function definition 6. fbgl_draw_texture specifies a const pointer to the texture resource, possibly allowing for compiler optimizations 7. fbgl_set_bg and fbgl_put_pixel now use #ifdef DEBUG to compile away checks in release builds, for faster performance 8. various const-correctness improvements 9. all required UNIX headers have been imported so that fbgl_check_esc_key does not give any more warnings All examples have been tested (on my local machine, so take this with a grain of salt) --- examples/empty_example.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 examples/empty_example.c (limited to 'examples/empty_example.c') diff --git a/examples/empty_example.c b/examples/empty_example.c new file mode 100644 index 0000000..cbb69c4 --- /dev/null +++ b/examples/empty_example.c @@ -0,0 +1,53 @@ +#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; +} -- cgit v1.2.3 From 064f53407750371bbe30c74d5abbb36255f7a5b0 Mon Sep 17 00:00:00 2001 From: dario-loi Date: Sun, 24 Nov 2024 19:23:53 +0100 Subject: Formatted according to file --- examples/.gitignore | 1 - examples/empty_example.c | 2 +- examples/raw_mode.c | 2 +- examples/rectangle.c | 2 +- examples/red.c | 2 +- examples/texture.c | 2 +- fbgl.h | 816 ++++++++++++++++++++++++----------------------- 7 files changed, 421 insertions(+), 406 deletions(-) delete mode 100644 examples/.gitignore (limited to 'examples/empty_example.c') diff --git a/examples/.gitignore b/examples/.gitignore deleted file mode 100644 index 4b44f82..0000000 --- a/examples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -build / core.* diff --git a/examples/empty_example.c b/examples/empty_example.c index cbb69c4..09f7d88 100644 --- a/examples/empty_example.c +++ b/examples/empty_example.c @@ -1,7 +1,7 @@ #define FBGL_IMPLEMENTATION //#define FBGL_HIDE_CURSOR #define FBGL_USE_FREETYPE -#include "../fbgl.h" +#include "fbgl.h" #include #include diff --git a/examples/raw_mode.c b/examples/raw_mode.c index 449a824..de97e78 100644 --- a/examples/raw_mode.c +++ b/examples/raw_mode.c @@ -1,5 +1,5 @@ #define FBGL_IMPLEMENTATION -#include "../fbgl.h" +#include "fbgl.h" #include int main(int argc, char *argv[]) diff --git a/examples/rectangle.c b/examples/rectangle.c index ecc1afd..1b3a6f7 100644 --- a/examples/rectangle.c +++ b/examples/rectangle.c @@ -1,5 +1,5 @@ #define FBGL_IMPLEMENTATION -#include "../fbgl.h" +#include "fbgl.h" int main(int argc, char *argv[]) { diff --git a/examples/red.c b/examples/red.c index 3809813..c074143 100644 --- a/examples/red.c +++ b/examples/red.c @@ -1,5 +1,5 @@ #define FBGL_IMPLEMENTATION -#include "../fbgl.h" +#include "fbgl.h" #include int main(int argc, char *argv[]) diff --git a/examples/texture.c b/examples/texture.c index da614d4..03311ea 100644 --- a/examples/texture.c +++ b/examples/texture.c @@ -1,5 +1,5 @@ #define FBGL_IMPLEMENTATION -#include "../fbgl.h" +#include "fbgl.h" #include #include #include // for usleep diff --git a/fbgl.h b/fbgl.h index 7c75156..d92bfb7 100644 --- a/fbgl.h +++ b/fbgl.h @@ -52,50 +52,50 @@ * Structs */ typedef struct fbgl { - int32_t width; - int32_t height; - int32_t fd; - uint32_t screen_size; - uint32_t* pixels; - struct fb_var_screeninfo vinfo; // Variable screen information - struct fb_fix_screeninfo finfo; // Fixed screen information + int32_t width; + int32_t height; + int32_t fd; + uint32_t screen_size; + uint32_t *pixels; + struct fb_var_screeninfo vinfo; // Variable screen information + struct fb_fix_screeninfo finfo; // Fixed screen information } fbgl_t; typedef struct fbgl_window { - int32_t x; // Top-left x-coordinate of the window - int32_t y; // Top-left y-coordinate of the window - uint32_t width; // Width of the window - uint32_t height; // Height of the window - fbgl_t* fb; // Pointer to the framebuffer context + int32_t x; // Top-left x-coordinate of the window + int32_t y; // Top-left y-coordinate of the window + uint32_t width; // Width of the window + uint32_t height; // Height of the 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 + 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; + int32_t x; + int32_t y; } fbgl_point_t; typedef struct fbgl_tga_texture { - uint16_t width; - uint16_t height; - uint32_t* data; + uint16_t width; + uint16_t height; + uint32_t *data; } fbgl_tga_texture_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 - bool is_initialized; // Track if keyboard is initialized + bool keys[FBGL_MAX_KEYS]; // Current state of each key + bool prev_keys[FBGL_MAX_KEYS]; // Previous state of each key + bool is_initialized; // Track if keyboard is initialized } fbgl_keyboard_t; /** @@ -109,30 +109,30 @@ static fbgl_keyboard_t keyboard = { 0 }; #include int fbgl_hide_cursor(int fd) { - int tty_fd = open("/dev/tty0", O_RDWR); - if (tty_fd == -1) { - perror("Error opening /dev/tty0"); - return -1; - } - - if (ioctl(tty_fd, KDSETMODE, KD_GRAPHICS) == -1) { - perror("Error setting graphics mode"); - close(tty_fd); - return -1; - } - - close(tty_fd); - return 0; + int tty_fd = open("/dev/tty0", O_RDWR); + if (tty_fd == -1) { + perror("Error opening /dev/tty0"); + return -1; + } + + if (ioctl(tty_fd, KDSETMODE, KD_GRAPHICS) == -1) { + perror("Error setting graphics mode"); + close(tty_fd); + return -1; + } + + close(tty_fd); + return 0; } #endif // FBGL_HIDE_CURSOR #ifdef FBGL_USE_FREETYPE FT_Library fbgl_freetype_init(); 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); +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 @@ -142,8 +142,8 @@ extern "C" { /** * General purpose methods */ -char const* fbgl_name_info(void); -char const* fbgl_version_info(void); +char const *fbgl_name_info(void); +char const *fbgl_version_info(void); void fbgl_enable_raw_mode(); void fbgl_disable_raw_mode(); void fbgl_cleanup(int sig); @@ -151,15 +151,15 @@ int fbgl_check_esc_key(); void fbgl_set_signal_handlers(); /*Create and destroy methods*/ -int fbgl_init(const char* device, fbgl_t* fb); -void fbgl_destroy(fbgl_t* fb); +int fbgl_init(const char *device, fbgl_t *fb); +void fbgl_destroy(fbgl_t *fb); /** * Drawing functions */ void fbgl_clear(uint32_t color); -void fbgl_put_pixel(int x, int y, uint32_t color, fbgl_t* fb); -void fbgl_draw_line(fbgl_point_t x, fbgl_point_t y, uint32_t color, fbgl_t* fb); +void fbgl_put_pixel(int x, int y, uint32_t color, fbgl_t *fb); +void fbgl_draw_line(fbgl_point_t x, fbgl_point_t y, uint32_t color, fbgl_t *fb); /** * Display methods @@ -169,26 +169,27 @@ void fbgl_display(); /** * Access framebuffer data methods */ -uint32_t* fb_get_data(fbgl_t const* fb); -uint32_t fb_get_width(fbgl_t const* fb); -uint32_t fb_get_height(fbgl_t const* fb); +uint32_t *fb_get_data(fbgl_t const *fb); +uint32_t fb_get_width(fbgl_t const *fb); +uint32_t fb_get_height(fbgl_t const *fb); /** * Shapes */ void fbgl_draw_rectangle_outline(fbgl_point_t top_left, - fbgl_point_t bottom_right, uint32_t color, - fbgl_t* fb); + fbgl_point_t bottom_right, uint32_t color, + fbgl_t *fb); void fbgl_draw_rectangle_filled(fbgl_point_t top_left, - fbgl_point_t bottom_right, uint32_t color, - fbgl_t* fb); + fbgl_point_t bottom_right, uint32_t color, + fbgl_t *fb); /** * texture */ -fbgl_tga_texture_t* fbgl_load_tga_texture(const char* path); -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); +fbgl_tga_texture_t *fbgl_load_tga_texture(const char *path); +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); /** * Keyboard @@ -202,446 +203,461 @@ bool fbgl_key_down(unsigned char key); #ifdef FBGL_IMPLEMENTATION -char const* fbgl_name_info(void) +char const *fbgl_name_info(void) { - return NAME; + return NAME; } -char const* fbgl_version_info(void) +char const *fbgl_version_info(void) { - return VERSION; + return VERSION; } -int fbgl_init(const char* device, fbgl_t* fb) +int fbgl_init(const char *device, fbgl_t *fb) { - if (!fb) { - fprintf(stderr, "Error: fbgl_t pointer is NULL."); - return -1; - } - - fb->fd = device == NULL ? open(DEFAULT_FB, O_RDWR) : open(device, O_RDWR); - if (fb->fd == -1) { - perror("Error openning framebuffer device"); - return -1; - } - - if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->finfo) == -1) { - perror("Error: Reading fixed information."); - close(fb->fd); - return -1; - } - if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vinfo) == -1) { - perror("Error reading variable information"); - close(fb->fd); - return -1; - } + if (!fb) { + fprintf(stderr, "Error: fbgl_t pointer is NULL."); + return -1; + } + + fb->fd = device == NULL ? open(DEFAULT_FB, O_RDWR) : + open(device, O_RDWR); + if (fb->fd == -1) { + perror("Error openning framebuffer device"); + return -1; + } + + if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->finfo) == -1) { + perror("Error: Reading fixed information."); + close(fb->fd); + return -1; + } + if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vinfo) == -1) { + perror("Error reading variable information"); + close(fb->fd); + return -1; + } #ifdef FBGL_HIDE_CURSOR - fbgl_hide_cursor(fb->fd); - fbgl_set_signal_handlers(); - fbgl_enable_raw_mode(); + fbgl_hide_cursor(fb->fd); + fbgl_set_signal_handlers(); + fbgl_enable_raw_mode(); #endif // FBGL_HIDE_CURSOR - fb->width = fb->vinfo.xres; - fb->height = fb->vinfo.yres; - fb->screen_size = fb->finfo.smem_len; - - // Map framebuffer to memory - fb->pixels = (uint32_t*)mmap(NULL, fb->screen_size, - PROT_READ | PROT_WRITE, MAP_SHARED, - fb->fd, 0); - if (fb->pixels == MAP_FAILED) { - perror("Error mapping framebuffer device to memory"); - close(fb->fd); - return -1; - } - - return 0; + fb->width = fb->vinfo.xres; + fb->height = fb->vinfo.yres; + fb->screen_size = fb->finfo.smem_len; + + // Map framebuffer to memory + fb->pixels = (uint32_t *)mmap(NULL, fb->screen_size, + PROT_READ | PROT_WRITE, MAP_SHARED, + fb->fd, 0); + if (fb->pixels == MAP_FAILED) { + perror("Error mapping framebuffer device to memory"); + close(fb->fd); + return -1; + } + + return 0; } -void fbgl_destroy(fbgl_t* fb) +void fbgl_destroy(fbgl_t *fb) { - if (!fb || fb->fd == -1) { - fprintf(stderr, - "Error: framebuffer not initialized or already destroyed.\n"); - return; - } + if (!fb || fb->fd == -1) { + fprintf(stderr, + "Error: framebuffer not initialized or already destroyed.\n"); + return; + } - if (fb->pixels && fb->pixels != MAP_FAILED) { - munmap(fb->pixels, fb->screen_size); - } + if (fb->pixels && fb->pixels != MAP_FAILED) { + munmap(fb->pixels, fb->screen_size); + } - close(fb->fd); - fb->fd = -1; + close(fb->fd); + fb->fd = -1; #ifdef FBGL_HIDE_CURSOR - fbgl_disable_raw_mode(); + fbgl_disable_raw_mode(); #endif // FBGL_HIDE_CURSOR } -void fbgl_set_bg(fbgl_t* fb, uint32_t color) +void fbgl_set_bg(fbgl_t *fb, uint32_t color) { #ifdef DEBUG - if (!fb || fb->fd == -1) { - fprintf(stderr, "Error: framebuffer not initialized.\n"); - return; - } + if (!fb || fb->fd == -1) { + fprintf(stderr, "Error: framebuffer not initialized.\n"); + return; + } #endif // DEBUG - // Fill the entire framebuffer with the specified color - for (int i = 0; i < fb->screen_size; i++) { - fb->pixels[i] = color; - } + // Fill the entire framebuffer with the specified color + for (int i = 0; i < fb->screen_size; i++) { + fb->pixels[i] = color; + } } -void fbgl_put_pixel(int x, int y, uint32_t color, fbgl_t* fb) +void fbgl_put_pixel(int x, int y, uint32_t color, fbgl_t *fb) { #ifdef DEBUG - if (!fb || !fb->pixels) { - fprintf(stderr, "Error: framebuffer not initialized.\n"); - return; - } - - if (x < 0 || x >= fb->width || y < 0 || y >= fb->height) { - return; // Ignore out-of-bound coordinates - } + if (!fb || !fb->pixels) { + fprintf(stderr, "Error: framebuffer not initialized.\n"); + return; + } + + if (x < 0 || x >= fb->width || y < 0 || y >= fb->height) { + return; // Ignore out-of-bound coordinates + } #endif // DEBUG - const size_t index = y * fb->width + x; - fb->pixels[index] = color; + const size_t index = y * fb->width + x; + fb->pixels[index] = color; } void fbgl_enable_raw_mode() { - struct termios raw; - - if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) { - perror("tcgetattr"); - exit(EXIT_FAILURE); - } - raw = orig_termios; - raw.c_lflag &= ~(ECHO | ICANON); - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) { - perror("tcsetattr"); - exit(EXIT_FAILURE); - } + struct termios raw; + + if (tcgetattr(STDIN_FILENO, &orig_termios) == -1) { + perror("tcgetattr"); + exit(EXIT_FAILURE); + } + raw = orig_termios; + raw.c_lflag &= ~(ECHO | ICANON); + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw) == -1) { + perror("tcsetattr"); + exit(EXIT_FAILURE); + } } void fbgl_disable_raw_mode() { - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) { - perror("tcsetattr"); - } + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) { + perror("tcsetattr"); + } } void fbgl_cleanup(int sig) { - fbgl_disable_raw_mode(); - printf("\033[2J\033[H"); // Clear the terminal screen and move the cursor to top-left - exit(sig); + fbgl_disable_raw_mode(); + printf("\033[2J\033[H"); // Clear the terminal screen and move the cursor to top-left + exit(sig); } int fbgl_check_esc_key() { - char c; - struct timeval tv = { 0, 0 }; // Timeout of 0, to poll immediately - fd_set fds; - FD_ZERO(&fds); - FD_SET(STDIN_FILENO, &fds); - - // Check if there's input available - if (select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv) == -1) { - perror("select"); - return 0; - } - - if (FD_ISSET(STDIN_FILENO, &fds)) { - if (read(STDIN_FILENO, &c, 1) == -1) { - perror("read"); - return 0; - } - return c == 27; // ASCII value of the `Esc` key - } - - return 0; + char c; + struct timeval tv = { 0, 0 }; // Timeout of 0, to poll immediately + fd_set fds; + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + + // Check if there's input available + if (select(STDIN_FILENO + 1, &fds, NULL, NULL, &tv) == -1) { + perror("select"); + return 0; + } + + if (FD_ISSET(STDIN_FILENO, &fds)) { + if (read(STDIN_FILENO, &c, 1) == -1) { + perror("read"); + return 0; + } + return c == 27; // ASCII value of the `Esc` key + } + + return 0; } void fbgl_set_signal_handlers() { - struct sigaction sa; - sa.sa_handler = fbgl_cleanup; - sa.sa_flags = 0; - sigemptyset(&sa.sa_mask); - - if (sigaction(SIGINT, &sa, NULL) == -1 || sigaction(SIGTERM, &sa, NULL) == -1) { - perror("sigaction"); - exit(EXIT_FAILURE); - } + struct sigaction sa; + sa.sa_handler = fbgl_cleanup; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + + if (sigaction(SIGINT, &sa, NULL) == -1 || + sigaction(SIGTERM, &sa, NULL) == -1) { + perror("sigaction"); + exit(EXIT_FAILURE); + } } #ifdef FBGL_USE_FREETYPE FT_Library fbgl_freetype_init() { - FT_Library library; - if (FT_Init_FreeType(&library)) { - fprintf(stderr, "Could not init FreeType Library\n"); - return NULL; - } - return library; + 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); - } + if (library) { + FT_Done_FreeType(library); + } } -FT_Face fbgl_load_font(FT_Library library, const char* font_path, int font_size) +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; + 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) +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 (int32_t j = 0; j < bitmap.rows; j++) { - for (int32_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; - } + while (*text) { + FT_Load_Char(face, *text, FT_LOAD_RENDER); + FT_Bitmap bitmap = face->glyph->bitmap; + + // Draw the bitmap to framebuffer + for (int32_t j = 0; j < bitmap.rows; j++) { + for (int32_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) + fbgl_t *buffer) { - const int32_t dx = abs(y.x - x.x); - const int32_t dy = abs(y.y - x.y); + const int32_t dx = abs(y.x - x.x); + const int32_t dy = abs(y.y - x.y); - const int32_t sx = (x.x < y.x) ? 1 : -1; - const int32_t sy = (x.y < y.y) ? 1 : -1; + const int32_t sx = (x.x < y.x) ? 1 : -1; + const int32_t sy = (x.y < y.y) ? 1 : -1; - int32_t err = dx - dy; + int32_t err = dx - dy; - while (1) { - // Set the pixel at the current position - fbgl_put_pixel(x.x, x.y, color, buffer); + while (1) { + // Set the pixel at the current position + fbgl_put_pixel(x.x, x.y, color, buffer); - // If we've reached the end point, break - if (x.x >= y.x && x.y >= y.y) - break; + // If we've reached the end point, break + if (x.x >= y.x && x.y >= y.y) + break; - const int32_t e2 = 2 * err; + const int32_t e2 = 2 * err; - if (e2 > -dy) { - err -= dy; - x.x += sx; - } + if (e2 > -dy) { + err -= dy; + x.x += sx; + } - if (e2 < dx) { - err += dx; - x.y += sy; - } - } + if (e2 < dx) { + err += dx; + x.y += sy; + } + } } void fbgl_draw_rectangle_outline(fbgl_point_t top_left, - fbgl_point_t bottom_right, uint32_t color, - fbgl_t* fb) + fbgl_point_t bottom_right, uint32_t color, + fbgl_t *fb) { - // Top horizontal line - for (int x = top_left.x; x < bottom_right.x; x++) { - fbgl_put_pixel(x, top_left.y, color, fb); - } - - // Bottom horizontal line - for (int x = top_left.x; x < bottom_right.x; x++) { - fbgl_put_pixel(x, bottom_right.y - 1, color, fb); - } - - // Left vertical line - for (int y = top_left.y; y < bottom_right.y; y++) { - fbgl_put_pixel(top_left.x, y, color, fb); - } - - // Right vertical line - for (int y = top_left.y; y < bottom_right.y; y++) { - fbgl_put_pixel(bottom_right.x - 1, y, color, fb); - } + // Top horizontal line + for (int x = top_left.x; x < bottom_right.x; x++) { + fbgl_put_pixel(x, top_left.y, color, fb); + } + + // Bottom horizontal line + for (int x = top_left.x; x < bottom_right.x; x++) { + fbgl_put_pixel(x, bottom_right.y - 1, color, fb); + } + + // Left vertical line + for (int y = top_left.y; y < bottom_right.y; y++) { + fbgl_put_pixel(top_left.x, y, color, fb); + } + + // Right vertical line + for (int y = top_left.y; y < bottom_right.y; y++) { + fbgl_put_pixel(bottom_right.x - 1, y, color, fb); + } } void fbgl_draw_rectangle_filled(fbgl_point_t top_left, - fbgl_point_t bottom_right, uint32_t color, - fbgl_t* fb) + fbgl_point_t bottom_right, uint32_t color, + fbgl_t *fb) { - for (int32_t y = top_left.y; y < bottom_right.y; y++) { - // Manually set each pixel in the row - for (int32_t x = top_left.x; x < bottom_right.x; x++) { - fbgl_put_pixel(x, y, color, fb); - } - } + for (int32_t y = top_left.y; y < bottom_right.y; y++) { + // Manually set each pixel in the row + for (int32_t x = top_left.x; x < bottom_right.x; x++) { + fbgl_put_pixel(x, y, color, fb); + } + } } -fbgl_tga_texture_t* fbgl_load_tga_texture(const char* path) +fbgl_tga_texture_t *fbgl_load_tga_texture(const char *path) { - FILE* file = fopen(path, "rb"); - if (!file) { - perror("Unable to open texture file"); - return NULL; - } - - // TGA header structure - uint8_t header[18]; - if (fread(header, 1, sizeof(header), file) != sizeof(header)) { - perror("Error reading TGA header"); - fclose(file); - return NULL; - } - - // Allocate texture structure - fbgl_tga_texture_t* texture = (fbgl_tga_texture_t*)malloc(sizeof(fbgl_tga_texture_t)); - if (!texture) { - perror("Failed to allocate texture structure"); - fclose(file); - return NULL; - } - - // Extract dimensions from header - texture->width = header[12] | (header[13] << 8); - texture->height = header[14] | (header[15] << 8); - uint8_t bits_per_pixel = header[16]; - uint8_t image_descriptor = header[17]; - - // Verify format support - if (bits_per_pixel != 24 && bits_per_pixel != 32) { - fprintf(stderr, - "Unsupported TGA bit depth: %d (only 24 and 32-bit supported)\n", - bits_per_pixel); - free(texture); - fclose(file); - return NULL; - } - - // Skip image ID field - if (header[0]) { - fseek(file, header[0], SEEK_CUR); - } - - // Allocate pixel data - size_t pixel_count = texture->width * texture->height; - texture->data = (uint32_t*)malloc(pixel_count * sizeof(uint32_t)); - if (!texture->data) { - perror("Failed to allocate pixel data"); - free(texture); - fclose(file); - return NULL; - } - - // Read pixel data - uint8_t* pixel_buffer = (uint8_t*)malloc(bits_per_pixel / 8); - if (!pixel_buffer) { - perror("Failed to allocate pixel buffer"); - free(texture->data); - free(texture); - fclose(file); - return NULL; - } - - // Determine if image is flipped (based on image descriptor) - bool bottom_up = !(image_descriptor & 0x20); - - for (size_t i = 0; i < pixel_count; i++) { - size_t pixel_index = bottom_up ? (texture->height - 1 - (i / texture->width)) * texture->width + (i % texture->width) : i; - - if (fread(pixel_buffer, 1, bits_per_pixel / 8, file) != bits_per_pixel / 8) { - perror("Error reading pixel data"); - free(pixel_buffer); - free(texture->data); - free(texture); - fclose(file); - return NULL; - } - - // Convert BGR(A) to RGBA - uint32_t pixel = 0xFF000000; // Default alpha to 255 - pixel |= pixel_buffer[2] << 16; // R - pixel |= pixel_buffer[1] << 8; // G - pixel |= pixel_buffer[0]; // B - if (bits_per_pixel == 32) { - pixel = (pixel & 0x00FFFFFF) | (pixel_buffer[3] << 24); // A - } - - texture->data[pixel_index] = pixel; - } - - free(pixel_buffer); - fclose(file); - return texture; + FILE *file = fopen(path, "rb"); + if (!file) { + perror("Unable to open texture file"); + return NULL; + } + + // TGA header structure + uint8_t header[18]; + if (fread(header, 1, sizeof(header), file) != sizeof(header)) { + perror("Error reading TGA header"); + fclose(file); + return NULL; + } + + // Allocate texture structure + fbgl_tga_texture_t *texture = + (fbgl_tga_texture_t *)malloc(sizeof(fbgl_tga_texture_t)); + if (!texture) { + perror("Failed to allocate texture structure"); + fclose(file); + return NULL; + } + + // Extract dimensions from header + texture->width = header[12] | (header[13] << 8); + texture->height = header[14] | (header[15] << 8); + uint8_t bits_per_pixel = header[16]; + uint8_t image_descriptor = header[17]; + + // Verify format support + if (bits_per_pixel != 24 && bits_per_pixel != 32) { + fprintf(stderr, + "Unsupported TGA bit depth: %d (only 24 and 32-bit supported)\n", + bits_per_pixel); + free(texture); + fclose(file); + return NULL; + } + + // Skip image ID field + if (header[0]) { + fseek(file, header[0], SEEK_CUR); + } + + // Allocate pixel data + size_t pixel_count = texture->width * texture->height; + texture->data = (uint32_t *)malloc(pixel_count * sizeof(uint32_t)); + if (!texture->data) { + perror("Failed to allocate pixel data"); + free(texture); + fclose(file); + return NULL; + } + + // Read pixel data + uint8_t *pixel_buffer = (uint8_t *)malloc(bits_per_pixel / 8); + if (!pixel_buffer) { + perror("Failed to allocate pixel buffer"); + free(texture->data); + free(texture); + fclose(file); + return NULL; + } + + // Determine if image is flipped (based on image descriptor) + bool bottom_up = !(image_descriptor & 0x20); + + for (size_t i = 0; i < pixel_count; i++) { + size_t pixel_index = + bottom_up ? + (texture->height - 1 - (i / texture->width)) * + texture->width + + (i % texture->width) : + i; + + if (fread(pixel_buffer, 1, bits_per_pixel / 8, file) != + bits_per_pixel / 8) { + perror("Error reading pixel data"); + free(pixel_buffer); + free(texture->data); + free(texture); + fclose(file); + return NULL; + } + + // Convert BGR(A) to RGBA + uint32_t pixel = 0xFF000000; // Default alpha to 255 + pixel |= pixel_buffer[2] << 16; // R + pixel |= pixel_buffer[1] << 8; // G + pixel |= pixel_buffer[0]; // B + if (bits_per_pixel == 32) { + pixel = (pixel & 0x00FFFFFF) | + (pixel_buffer[3] << 24); // A + } + + texture->data[pixel_index] = pixel; + } + + free(pixel_buffer); + fclose(file); + return texture; } -void fbgl_destroy_texture(fbgl_tga_texture_t* texture) +void fbgl_destroy_texture(fbgl_tga_texture_t *texture) { - if (texture) { - free(texture->data); - free(texture); - } + if (texture) { + free(texture->data); + free(texture); + } } -void fbgl_draw_texture(fbgl_t* fb, fbgl_tga_texture_t const* texture, int32_t x, int32_t y) +void fbgl_draw_texture(fbgl_t *fb, fbgl_tga_texture_t const *texture, int32_t x, + int32_t y) { - if (!fb || !texture || !texture->data) { - return; - } - - for (int ty = 0; ty < texture->height; ty++) { - for (int tx = 0; tx < texture->width; tx++) { - int screen_x = x + tx; - int screen_y = y + ty; - - // Skip if outside screen bounds - if (screen_x < 0 || screen_x >= fb->width || screen_y < 0 || screen_y >= fb->height) { - continue; - } - - uint32_t pixel = texture->data[ty * texture->width + tx]; - // Only draw if pixel is not fully transparent - if ((pixel & 0xFF000000) != 0) { - fbgl_put_pixel(screen_x, screen_y, pixel, fb); - } - } - } + if (!fb || !texture || !texture->data) { + return; + } + + for (int ty = 0; ty < texture->height; ty++) { + for (int tx = 0; tx < texture->width; tx++) { + int screen_x = x + tx; + int screen_y = y + ty; + + // Skip if outside screen bounds + if (screen_x < 0 || screen_x >= fb->width || + screen_y < 0 || screen_y >= fb->height) { + continue; + } + + uint32_t pixel = + texture->data[ty * texture->width + tx]; + // Only draw if pixel is not fully transparent + if ((pixel & 0xFF000000) != 0) { + fbgl_put_pixel(screen_x, screen_y, pixel, fb); + } + } + } } -uint32_t fb_get_width(fbgl_t const* fb) +uint32_t fb_get_width(fbgl_t const *fb) { - return fb->width; + return fb->width; } -uint32_t fb_get_height(fbgl_t const* fb) +uint32_t fb_get_height(fbgl_t const *fb) { - return fb->height; + return fb->height; } -uint32_t* fb_get_data(fbgl_t const* fb) +uint32_t *fb_get_data(fbgl_t const *fb) { - return fb->pixels; + return fb->pixels; } #endif // FBGL_IMPLEMENTATION -- cgit v1.2.3 From 274cacc5fadb3c3a220b833f027eee47cbda824c Mon Sep 17 00:00:00 2001 From: dario-loi Date: Sun, 24 Nov 2024 20:09:43 +0100 Subject: Worked on minor changes for warnings --- CMakeLists.txt | 1 + examples/empty_example.c | 2 +- fbgl.h | 36 ++++++++++++++++++------------------ 3 files changed, 20 insertions(+), 19 deletions(-) (limited to 'examples/empty_example.c') diff --git a/CMakeLists.txt b/CMakeLists.txt index 03453ef..02aa36d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ include_directories(${FREETYPE2_INCLUDE_DIRS}) function(add_example NAME) add_executable("${NAME}" "${EXAMPLES_DIR}/${NAME}.c" "${FBGL_HEADER}") target_compile_features("${NAME}" PRIVATE c_std_99) + target_compile_options("${NAME}" PRIVATE -Wall -Wextra -Wpedantic) target_include_directories("${NAME}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}") target_link_libraries("${NAME}" PRIVATE ${FREETYPE2_LIBRARIES}) add_custom_target("run_${NAME}" COMMAND "${NAME}" VERBATIM) diff --git a/examples/empty_example.c b/examples/empty_example.c index 09f7d88..352824a 100644 --- a/examples/empty_example.c +++ b/examples/empty_example.c @@ -43,7 +43,7 @@ int main() fprintf(stdout, "ESC pressed\n"); break; } - //fbgl_set_bg(&buffer, i++); // Set background color to + //fbgl_set_bg(&buffer, i++); // Set background color to for (int i = 0x000000; i <= 0xFFFFFF; i++) { fbgl_set_bg(&buffer, i); } diff --git a/fbgl.h b/fbgl.h index d92bfb7..75abb6f 100644 --- a/fbgl.h +++ b/fbgl.h @@ -127,7 +127,7 @@ int fbgl_hide_cursor(int fd) #endif // FBGL_HIDE_CURSOR #ifdef FBGL_USE_FREETYPE -FT_Library fbgl_freetype_init(); +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); @@ -144,11 +144,11 @@ extern "C" { */ char const *fbgl_name_info(void); char const *fbgl_version_info(void); -void fbgl_enable_raw_mode(); -void fbgl_disable_raw_mode(); +void fbgl_enable_raw_mode(void); +void fbgl_disable_raw_mode(void); void fbgl_cleanup(int sig); -int fbgl_check_esc_key(); -void fbgl_set_signal_handlers(); +int fbgl_check_esc_key(void); +void fbgl_set_signal_handlers(void); /*Create and destroy methods*/ int fbgl_init(const char *device, fbgl_t *fb); @@ -164,7 +164,7 @@ void fbgl_draw_line(fbgl_point_t x, fbgl_point_t y, uint32_t color, fbgl_t *fb); /** * Display methods */ -void fbgl_display(); +void fbgl_display(void); /** * Access framebuffer data methods @@ -194,9 +194,9 @@ void fbgl_draw_texture(fbgl_t *fb, fbgl_tga_texture_t const *texture, int32_t x, /** * Keyboard */ -int fbgl_keyboard_init(); -void fbgl_keyboard_clean(); -void fbgl_keyboard_update(); +int fbgl_keyboard_init(void); +void fbgl_keyboard_clean(void); +void fbgl_keyboard_update(void); bool fbgl_key_pressed(unsigned char key); bool fbgl_key_released(unsigned char key); bool fbgl_key_down(unsigned char key); @@ -291,7 +291,7 @@ void fbgl_set_bg(fbgl_t *fb, uint32_t color) #endif // DEBUG // Fill the entire framebuffer with the specified color - for (int i = 0; i < fb->screen_size; i++) { + for (uint32_t i = 0; i < fb->width * fb->height; i++) { fb->pixels[i] = color; } } @@ -313,7 +313,7 @@ void fbgl_put_pixel(int x, int y, uint32_t color, fbgl_t *fb) fb->pixels[index] = color; } -void fbgl_enable_raw_mode() +void fbgl_enable_raw_mode(void) { struct termios raw; @@ -329,7 +329,7 @@ void fbgl_enable_raw_mode() } } -void fbgl_disable_raw_mode() +void fbgl_disable_raw_mode(void) { if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios) == -1) { perror("tcsetattr"); @@ -343,7 +343,7 @@ void fbgl_cleanup(int sig) exit(sig); } -int fbgl_check_esc_key() +int fbgl_check_esc_key(void) { char c; struct timeval tv = { 0, 0 }; // Timeout of 0, to poll immediately @@ -368,7 +368,7 @@ int fbgl_check_esc_key() return 0; } -void fbgl_set_signal_handlers() +void fbgl_set_signal_handlers(void) { struct sigaction sa; sa.sa_handler = fbgl_cleanup; @@ -383,7 +383,7 @@ void fbgl_set_signal_handlers() } #ifdef FBGL_USE_FREETYPE -FT_Library fbgl_freetype_init() +FT_Library fbgl_freetype_init(void) { FT_Library library; if (FT_Init_FreeType(&library)) { @@ -419,8 +419,8 @@ void fbgl_render_freetype_text(fbgl_t *fb, FT_Library library, FT_Face face, FT_Bitmap bitmap = face->glyph->bitmap; // Draw the bitmap to framebuffer - for (int32_t j = 0; j < bitmap.rows; j++) { - for (int32_t i = 0; i < bitmap.width; i++) { + 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, @@ -707,4 +707,4 @@ AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ------------------------------------------------------------------------------ -*/ \ No newline at end of file +*/ -- cgit v1.2.3