summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--example/.gitignore3
-rw-r--r--example/CMakeLists.txt39
-rw-r--r--example/empty_example.c74
-rw-r--r--example/line.c7
-rw-r--r--example/raw_mode.c21
-rw-r--r--example/rectangle.c102
-rw-r--r--example/red.c13
-rw-r--r--fbgl.h853
8 files changed, 553 insertions, 559 deletions
diff --git a/example/.gitignore b/example/.gitignore
index 07ac165..4b44f82 100644
--- a/example/.gitignore
+++ b/example/.gitignore
@@ -1,2 +1 @@
-build/
-core.*
+build / core.*
diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt
index 411945a..837e6e8 100644
--- a/example/CMakeLists.txt
+++ b/example/CMakeLists.txt
@@ -1,24 +1,31 @@
cmake_minimum_required(VERSION 3.21)
-project(fbglExamples C)
+ project(fbglExamples C)
-include(../cmake/folders.cmake)
+ include(../ cmake / folders.cmake)
-if(PROJECT_IS_TOP_LEVEL)
- find_package(fbgl REQUIRED)
-endif()
+ if (PROJECT_IS_TOP_LEVEL) find_package(
+ fbgl REQUIRED) endif()
-add_custom_target(run-examples)
+ add_custom_target(run - examples)
-function(add_example NAME)
- add_executable("${NAME}" "${NAME}.c")
- target_link_libraries("${NAME}" PRIVATE fbgl::fbgl)
- target_compile_features("${NAME}" PRIVATE c_std_99)
- add_custom_target("run_${NAME}" COMMAND "${NAME}" VERBATIM)
- add_dependencies("run_${NAME}" "${NAME}")
- add_dependencies(run-examples "run_${NAME}")
-endfunction()
+ function(add_example NAME) add_executable(
+ "${NAME}"
+ "${NAME}.c") target_link_libraries("${NAME}" PRIVATE
+ fbgl::fbgl)
+ target_compile_features("${NAME}" PRIVATE c_std_99) add_custom_target(
+ "run_${NAME}" COMMAND
+ "${NAME}" VERBATIM)
+ add_dependencies(
+ "run_${NAME}"
+ "${NAME}")
+ add_dependencies(
+ run -
+ examples
+ "run_${NAME}") endfunction()
-add_example(empty_example)
+ add_example(
+ empty_example)
-add_folders(Example)
+ add_folders(
+ Example)
diff --git a/example/empty_example.c b/example/empty_example.c
index aee9232..cbb69c4 100644
--- a/example/empty_example.c
+++ b/example/empty_example.c
@@ -8,46 +8,46 @@
int main()
{
- printf("version %s\n", fbgl_version_info());
- printf("name %s\n", fbgl_name_info());
+ 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;
- }
+ 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_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;
- }
+ FT_Library library = fbgl_freetype_init();
+ if (!library) {
+ fbgl_destroy(&buffer);
+ return -1;
+ }
- // Render text to framebuffer
- fbgl_render_freetype_text(&buffer, library, face, "Hello, World!", 50, 50);
+ 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;
+ }
- // 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);
+ // 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;
+ fbgl_destroy(&buffer);
+ return 0;
}
diff --git a/example/line.c b/example/line.c
index 9d937cd..f20ec7e 100644
--- a/example/line.c
+++ b/example/line.c
@@ -11,11 +11,12 @@ int main(int argc, char *argv[])
fbgl_set_bg(&buffer, 0xFF0000);
fbgl_point_t start = { 0, 0 };
- fbgl_point_t end = { 1020, 1020};
- for(int i = 0; i < 1890; i++) {
+ fbgl_point_t end = { 1020, 1020 };
+ for (int i = 0; i < 1890; i++) {
start.x = i;
fbgl_draw_line(start, end, 0xFFFFFF, &buffer);
- for(int j = 0; j < 10000000; j++){}
+ for (int j = 0; j < 10000000; j++) {
+ }
}
fbgl_draw_line(start, end, 0x000000, &buffer);
diff --git a/example/raw_mode.c b/example/raw_mode.c
index 12127af..449a824 100644
--- a/example/raw_mode.c
+++ b/example/raw_mode.c
@@ -4,18 +4,17 @@
int main(int argc, char *argv[])
{
- fbgl_t fb;
- fbgl_init("/dev/fb0", &fb);
+ fbgl_t fb;
+ fbgl_init("/dev/fb0", &fb);
- fbgl_set_bg(&fb, 0xFFFFFF);
+ fbgl_set_bg(&fb, 0xFFFFFF);
- while(1) {
- if(fbgl_check_esc_key()) {
- printf("pressed");
- fbgl_set_bg(&fb, 0x000000);
+ while (1) {
+ if (fbgl_check_esc_key()) {
+ printf("pressed");
+ fbgl_set_bg(&fb, 0x000000);
+ }
}
- }
-
- return 0;
-}
+ return 0;
+}
diff --git a/example/rectangle.c b/example/rectangle.c
index 73f9c4b..ecc1afd 100644
--- a/example/rectangle.c
+++ b/example/rectangle.c
@@ -3,57 +3,59 @@
int main(int argc, char *argv[])
{
- fbgl_t buffer;
- if (fbgl_init("/dev/fb0", &buffer) == -1) {
- fprintf(stdout, "Error: could not open framebuffer device\n");
- return -1;
- }
-
- fbgl_set_bg(&buffer, 0xFFFFFF); // Set the background to white
-
- fbgl_point_t start = {100, 100};
- fbgl_point_t end = {200, 200};
- fbgl_draw_rectangle_outline(start, end, 0xFF0000, &buffer); // Draw red rectangle outline
-
- fbgl_point_t start2 = {600, 400};
- fbgl_point_t end2 = {800, 800};
- uint32_t colors[] = {0xFFC00, 0x00FF00, 0x0000FF, 0xFF00FF}; // Yellow, Green, Blue, Magenta
- size_t color_index = 0;
-
- // Initial position of the marquee rectangle
- int dx = 15; // Horizontal speed
- int dy = 8; // Vertical speed
-
- while (1) {
- // Clear the framebuffer (set background)
- fbgl_set_bg(&buffer, 0xFFFFFF);
-
-
- // Draw the moving filled rectangle
- fbgl_draw_rectangle_filled(start2, end2, colors[color_index], &buffer);
-
- // Move the filled rectangle by updating its position
- start2.x += dx;
- end2.x += dx;
- start2.y += dy;
- end2.y += dy;
-
- // Reverse direction if the rectangle hits the screen boundary
- if (start2.x <= 0 || end2.x >= buffer.width) {
- dx = -dx;
- color_index++;
- }
- if (start2.y <= 0 || end2.y >= buffer.height) {
- dy = -dy;
- color_index++;
- }
- if (color_index >= 4) {
- color_index = 0;
+ fbgl_t buffer;
+ if (fbgl_init("/dev/fb0", &buffer) == -1) {
+ fprintf(stdout, "Error: could not open framebuffer device\n");
+ return -1;
}
- usleep(50000); // Delay to make the animation visible (adjust as needed)
- }
+ fbgl_set_bg(&buffer, 0xFFFFFF); // Set the background to white
+
+ fbgl_point_t start = { 100, 100 };
+ fbgl_point_t end = { 200, 200 };
+ fbgl_draw_rectangle_outline(start, end, 0xFF0000,
+ &buffer); // Draw red rectangle outline
+
+ fbgl_point_t start2 = { 600, 400 };
+ fbgl_point_t end2 = { 800, 800 };
+ uint32_t colors[] = { 0xFFC00, 0x00FF00, 0x0000FF,
+ 0xFF00FF }; // Yellow, Green, Blue, Magenta
+ size_t color_index = 0;
+
+ // Initial position of the marquee rectangle
+ int dx = 15; // Horizontal speed
+ int dy = 8; // Vertical speed
+
+ while (1) {
+ // Clear the framebuffer (set background)
+ fbgl_set_bg(&buffer, 0xFFFFFF);
+
+ // Draw the moving filled rectangle
+ fbgl_draw_rectangle_filled(start2, end2, colors[color_index],
+ &buffer);
+
+ // Move the filled rectangle by updating its position
+ start2.x += dx;
+ end2.x += dx;
+ start2.y += dy;
+ end2.y += dy;
+
+ // Reverse direction if the rectangle hits the screen boundary
+ if (start2.x <= 0 || end2.x >= buffer.width) {
+ dx = -dx;
+ color_index++;
+ }
+ if (start2.y <= 0 || end2.y >= buffer.height) {
+ dy = -dy;
+ color_index++;
+ }
+ if (color_index >= 4) {
+ color_index = 0;
+ }
+
+ usleep(50000); // Delay to make the animation visible (adjust as needed)
+ }
- fbgl_destroy(&buffer);
- return 0;
+ fbgl_destroy(&buffer);
+ return 0;
}
diff --git a/example/red.c b/example/red.c
index 274bc31..7f64dbd 100644
--- a/example/red.c
+++ b/example/red.c
@@ -4,10 +4,11 @@
int main(int argc, char *argv[])
{
- fbgl_t fb;
- fbgl_init("/dev/fb0", &fb);
- fbgl_set_bg(&fb, 0xFF0000);
- while(1){}
-
- return 0;
+ fbgl_t fb;
+ fbgl_init("/dev/fb0", &fb);
+ fbgl_set_bg(&fb, 0xFF0000);
+ while (1) {
+ }
+
+ return 0;
}
diff --git a/fbgl.h b/fbgl.h
index ca0f2bf..455c3e9 100644
--- a/fbgl.h
+++ b/fbgl.h
@@ -27,114 +27,113 @@
#define VERSION "0.1.0"
#define NAME "FBGL"
#define DEFAULT_FB "/dev/fb0"
-#define #define FBGL_MAX_KEYS 256 // Maximum number of keys to track
+#define FBGL_MAX_KEYS 256 // Maximum number of keys to track
+#include <fcntl.h>
+#include <linux/fb.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stddef.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
-#include <unistd.h>
-#include <linux/fb.h>
-#include <stddef.h>
-#include <stdio.h>
#include <termios.h>
-#include <signal.h>
-#include <stdbool.h>
+#include <unistd.h>
#ifdef FBGL_USE_FREETYPE
#include <ft2build.h>
#include FT_FREETYPE_H
-#endif //FBGL_USE_FREETYPE
+#endif // FBGL_USE_FREETYPE
/**
-* Structs
-*/
+ * Structs
+ */
typedef struct fbgl {
- int width;
- int height;
- int fd;
- size_t screen_size;
- uint32_t *pixels;
- struct fb_var_screeninfo vinfo; // Variable screen information
- struct fb_fix_screeninfo finfo; // Fixed screen information
+ int width;
+ int height;
+ int fd;
+ size_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 {
- int x; // Top-left x-coordinate of the window
- int y; // Top-left y-coordinate of the window
- int width; // Width of the window
- int height; // Height of the window
- fbgl_t *fb; // Pointer to the framebuffer context
+ int x; // Top-left x-coordinate of the window
+ int y; // Top-left y-coordinate of the window
+ int width; // Width of the window
+ int 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 {
- size_t x;
- size_t y;
+ size_t x;
+ size_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 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 is_initialized; // Track if keyboard is initialized
} fbgl_keyboard_t;
-
/**
* Key state function and variables
- *
+ *
*/
static struct termios orig_termios;
-static fbgl_keyboard_t keyboard = {0};
+static fbgl_keyboard_t keyboard = { 0 };
#ifdef FBGL_HIDE_CURSOR
#include <linux/kd.h>
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
+#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);
-#endif //FBGL_USE_FREETYPE
+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" {
@@ -143,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);
@@ -152,48 +151,48 @@ 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
-*/
+ * 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);
void fbgl_set_bg();
/**
-* Display methods
-*/
+ * Display methods
+ */
void fbgl_display();
/**
-* Access framebuffer data methods
-*/
-uint32_t *fb_get_data(void);
+ * Access framebuffer data methods
+ */
+uint32_t* fb_get_data(void);
int fb_get_width(void);
int fb_get_height(void);
/**
-* Shapes
-*/
+ * 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 *texture, int x, int y);
+ * 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* texture, int x, int y);
/**
- * Keyboard
+ * Keyboard
*/
int fbgl_keyboard_init();
void fbgl_keyboard_clean();
@@ -204,179 +203,177 @@ 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();
-#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;
+ 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;
}
-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)
{
- if (!fb || fb->fd == -1) {
- fprintf(stderr, "Error: framebuffer not initialized.\n");
- return;
- }
-
- // Fill the entire framebuffer with the specified color
- for (size_t i = 0; i < (fb->width * fb->height); ++i) {
- fb->pixels[i] = color;
- }
+ if (!fb || fb->fd == -1) {
+ fprintf(stderr, "Error: framebuffer not initialized.\n");
+ return;
+ }
+
+ // Fill the entire framebuffer with the specified color
+ for (size_t i = 0; i < (fb->width * fb->height); ++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)
{
- if (!fb || !fb->pixels) {
- fprintf(stderr, "Error: framebuffer not initialized.\n");
- return;
- }
+ 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 (x < 0 || x >= fb->width || y < 0 || y >= fb->height) {
+ return; // Ignore out-of-bound coordinates
+ }
- size_t index = y * fb->width + x;
- fb->pixels[index] = color;
+ 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);
+ }
}
#endif
@@ -384,262 +381,250 @@ void fbgl_set_signal_handlers()
#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, int x, int y)
+void fbgl_render_freetype_text(fbgl_t* fb, FT_Library library, FT_Face face,
+ const char* text, int x, int y)
{
- while (*text) {
- FT_Load_Char(face, *text, FT_LOAD_RENDER);
- FT_Bitmap bitmap = face->glyph->bitmap;
-
- // Draw the bitmap to framebuffer
- for (int j = 0; j < bitmap.rows; j++) {
- for (int 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 (int j = 0; j < bitmap.rows; j++) {
+ for (int 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)
{
- int dx = abs(y.x - x.x);
- int dy = abs(y.y - x.y);
+ int dx = abs(y.x - x.x);
+ int dy = abs(y.y - x.y);
- int sx = (x.x < y.x) ? 1 : -1;
- int sy = (x.y < y.y) ? 1 : -1;
+ int sx = (x.x < y.x) ? 1 : -1;
+ int sy = (x.y < y.y) ? 1 : -1;
- int err = dx - dy;
+ int 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;
- int e2 = 2 * err;
+ int 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 (int y = top_left.y; y < bottom_right.y; y++) {
- // Manually set each pixel in the row
- for (int x = top_left.x; x < bottom_right.x; x++) {
- fbgl_put_pixel(x, y, color, fb);
- }
- }
+ for (int y = top_left.y; y < bottom_right.y; y++) {
+ // Manually set each pixel in the row
+ for (int 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 *texture, int x, int y)
+void fbgl_draw_texture(fbgl_t* fb, fbgl_tga_texture_t* texture, int x, int 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);
+ }
+ }
+ }
}
#ifdef __cplusplus
} // extern "C"