diff options
| -rw-r--r-- | .gitignore | 2 | ||||
| -rw-r--r-- | CMakeLists.txt | 32 | ||||
| -rw-r--r-- | example/CMakeLists.txt | 37 | ||||
| -rw-r--r-- | examples/empty_example.c | 53 | ||||
| -rw-r--r-- | examples/framebuf_info.c | 17 | ||||
| -rw-r--r-- | examples/line.c (renamed from example/line.c) | 7 | ||||
| -rw-r--r-- | examples/raw_mode.c | 20 | ||||
| -rw-r--r-- | examples/rectangle.c | 61 | ||||
| -rw-r--r-- | examples/red.c | 14 | ||||
| -rw-r--r-- | examples/texture.c (renamed from example/texture.c) | 2 | ||||
| -rw-r--r-- | fbgl.h | 116 |
11 files changed, 269 insertions, 92 deletions
@@ -1 +1,3 @@ +build +.vscode fbgl-test-env/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..02aa36d --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.11) + +project(fbglExamples C) + +add_custom_target(run-examples) + +set(FBGL_HEADER "fbgl.h") +set(EXAMPLES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/examples") + +# find freetype2 +find_package(PkgConfig REQUIRED) +pkg_check_modules(FREETYPE2 REQUIRED freetype2) +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) + add_dependencies("run_${NAME}" "${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 diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt deleted file mode 100644 index e7bf93e..0000000 --- a/example/CMakeLists.txt +++ /dev/null @@ -1,37 +0,0 @@ -cmake_minimum_required(VERSION 3.21) - -project(fbglExamples C) - -include(../ cmake / folders.cmake) - -if(PROJECT_IS_TOP_LEVEL) - find_package( - fbgl REQUIRED) -endif() - -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() - -add_example( - empty_example) - -add_folders( - Example) diff --git a/examples/empty_example.c b/examples/empty_example.c new file mode 100644 index 0000000..352824a --- /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 <stdio.h> +#include <stddef.h> + +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/framebuf_info.c b/examples/framebuf_info.c new file mode 100644 index 0000000..9d149fd --- /dev/null +++ b/examples/framebuf_info.c @@ -0,0 +1,17 @@ +#define FBGL_IMPLEMENTATION +#include "fbgl.h" + +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; + } + + fprintf(stdout, "Framebuffer width: %d\n", fb_get_width(&buffer)); + fprintf(stdout, "Framebuffer height: %d\n", fb_get_height(&buffer)); + fprintf(stdout, "Framebuffer screen size: %d\n", buffer.screen_size); + + return 0; +} diff --git a/example/line.c b/examples/line.c index f20ec7e..e22a113 100644 --- a/example/line.c +++ b/examples/line.c @@ -1,5 +1,5 @@ #define FBGL_IMPLEMENTATION -#include "../fbgl.h" +#include "fbgl.h" int main(int argc, char *argv[]) { @@ -9,14 +9,13 @@ int main(int argc, char *argv[]) return -1; } - fbgl_set_bg(&buffer, 0xFF0000); + fbgl_set_bg(&buffer, 0x00FF0000); fbgl_point_t start = { 0, 0 }; 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++) { - } + usleep(1000); // sleep for 1 millisecond } fbgl_draw_line(start, end, 0x000000, &buffer); diff --git a/examples/raw_mode.c b/examples/raw_mode.c new file mode 100644 index 0000000..de97e78 --- /dev/null +++ b/examples/raw_mode.c @@ -0,0 +1,20 @@ +#define FBGL_IMPLEMENTATION +#include "fbgl.h" +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + fbgl_t fb; + fbgl_init("/dev/fb0", &fb); + + fbgl_set_bg(&fb, 0xFFFFFF); + + while (1) { + if (fbgl_check_esc_key()) { + printf("pressed"); + fbgl_set_bg(&fb, 0x000000); + } + } + + return 0; +} diff --git a/examples/rectangle.c b/examples/rectangle.c new file mode 100644 index 0000000..1b3a6f7 --- /dev/null +++ b/examples/rectangle.c @@ -0,0 +1,61 @@ +#define FBGL_IMPLEMENTATION +#include "fbgl.h" + +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; + } + + usleep(50000); // Delay to make the animation visible (adjust as needed) + } + + fbgl_destroy(&buffer); + return 0; +} diff --git a/examples/red.c b/examples/red.c new file mode 100644 index 0000000..c074143 --- /dev/null +++ b/examples/red.c @@ -0,0 +1,14 @@ +#define FBGL_IMPLEMENTATION +#include "fbgl.h" +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + fbgl_t fb; + fbgl_init("/dev/fb0", &fb); + fbgl_set_bg(&fb, 0x00FF0000); + while (1) { + } + + return 0; +} diff --git a/example/texture.c b/examples/texture.c index d1c25bd..75a67d7 100644 --- a/example/texture.c +++ b/examples/texture.c @@ -1,5 +1,5 @@ #define FBGL_IMPLEMENTATION -#include "../fbgl.h" +#include "fbgl.h" #include <stdio.h> #include <stdlib.h> #include <unistd.h> // for usleep @@ -52,20 +52,20 @@ * Structs */ typedef struct fbgl { - int width; - int height; - int fd; - size_t screen_size; + 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 { - 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 + 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; @@ -82,8 +82,8 @@ typedef struct fbgl_psf2_header { } fbgl_psf2_header_t; typedef struct fbgl_point { - size_t x; - size_t y; + int32_t x; + int32_t y; } fbgl_point_t; typedef struct fbgl_tga_texture { @@ -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); @@ -160,19 +160,13 @@ void fbgl_destroy(fbgl_t *fb); 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_set_bg(); - -/** - * Display methods - */ -void fbgl_display(); /** * Access framebuffer data methods */ -uint32_t *fb_get_data(void); -int fb_get_width(void); -int fb_get_height(void); +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 @@ -189,14 +183,15 @@ void fbgl_draw_rectangle_filled(fbgl_point_t top_left, */ 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); +void fbgl_draw_texture(fbgl_t *fb, fbgl_tga_texture_t const *texture, int32_t x, + int32_t y); /** * 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); @@ -283,13 +278,15 @@ void fbgl_destroy(fbgl_t *fb) 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; } +#endif // DEBUG // Fill the entire framebuffer with the specified color - for (size_t i = 0; i < (fb->width * fb->height); ++i) { + for (int32_t i = 0; i < fb->width * fb->height; i++) { fb->pixels[i] = color; } } @@ -306,11 +303,12 @@ void fbgl_put_pixel(int x, int y, uint32_t color, fbgl_t *fb) return; // Ignore out-of-bound coordinates } #endif // FBGL_VALIDATE_PUT_PIXEL - size_t index = y * fb->width + x; + + const size_t index = y * fb->width + x; fb->pixels[index] = color; } -void fbgl_enable_raw_mode() +void fbgl_enable_raw_mode(void) { struct termios raw; @@ -326,7 +324,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"); @@ -340,7 +338,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 @@ -365,7 +363,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; @@ -379,10 +377,8 @@ void fbgl_set_signal_handlers() } } -#endif - #ifdef FBGL_USE_FREETYPE -FT_Library fbgl_freetype_init() +FT_Library fbgl_freetype_init(void) { FT_Library library; if (FT_Init_FreeType(&library)) { @@ -411,15 +407,15 @@ 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) + 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 (int j = 0; j < bitmap.rows; j++) { - for (int 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, @@ -434,26 +430,27 @@ void fbgl_render_freetype_text(fbgl_t *fb, FT_Library library, FT_Face face, } #endif // FBGL_USE_FREETYPE + void fbgl_draw_line(fbgl_point_t x, fbgl_point_t y, uint32_t color, fbgl_t *buffer) { - int dx = abs(y.x - x.x); - int dy = abs(y.y - x.y); + const int32_t dx = abs(y.x - x.x); + const int32_t dy = abs(y.y - x.y); - int sx = (x.x < y.x) ? 1 : -1; - int 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; - int 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); // If we've reached the end point, break - if (x.x == y.x && x.y == y.y) + if (x.x >= y.x && x.y >= y.y) break; - int e2 = 2 * err; + const int32_t e2 = 2 * err; if (e2 > -dy) { err -= dy; @@ -495,9 +492,9 @@ void fbgl_draw_rectangle_filled(fbgl_point_t top_left, fbgl_point_t bottom_right, uint32_t color, fbgl_t *fb) { - for (int y = top_left.y; y < bottom_right.y; y++) { + for (int32_t 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++) { + for (int32_t x = top_left.x; x < bottom_right.x; x++) { fbgl_put_pixel(x, y, color, fb); } } @@ -615,7 +612,8 @@ 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) +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; @@ -641,6 +639,24 @@ void fbgl_draw_texture(fbgl_t *fb, fbgl_tga_texture_t *texture, int x, int y) } } } + +uint32_t fb_get_width(fbgl_t const *fb) +{ + return fb->width; +} + +uint32_t fb_get_height(fbgl_t const *fb) +{ + return fb->height; +} + +uint32_t *fb_get_data(fbgl_t const *fb) +{ + return fb->pixels; +} + +#endif // FBGL_IMPLEMENTATION + #ifdef __cplusplus } // extern "C" #endif |
